feat: added QR code functionality

This commit is contained in:
Andrej Zavgorodnij 2020-07-22 14:53:06 +03:00
parent 0513b120de
commit 205857ea18
4 changed files with 188 additions and 0 deletions

15
go.mod Normal file
View File

@ -0,0 +1,15 @@
module p2p.org/dc4bc
go 1.13
require (
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7
github.com/mattn/go-gtk v0.0.0-20191030024613-af2e013261f5
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.6.1 // indirect
gocv.io/x/gocv v0.23.0
golang.org/x/image v0.0.0-20200618115811-c13761719519
golang.org/x/text v0.3.3 // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
)

56
main.go Normal file
View File

@ -0,0 +1,56 @@
package main
import (
_ "image/jpeg"
"log"
"os"
"os/exec"
"p2p.org/dc4bc/qr"
_ "image/gif"
_ "image/png"
_ "golang.org/x/image/bmp"
_ "golang.org/x/image/tiff"
_ "golang.org/x/image/webp"
)
func main() {
clearTerminal()
var data = "Hello, world!"
log.Println("A QR code will be shown on your screen.")
log.Println("Please take a photo of the QR code with your smartphone.")
log.Println("When you close the image, you will have 5 seconds to" +
"scan the QR code with your laptop's camera.")
err := qr.ShowQR(data)
if err != nil {
log.Fatalf("Failed to show QR code: %v", err)
}
var scannedData string
for {
clearTerminal()
if err != nil {
log.Printf("Failed to scan QR code: %v\n", err)
}
log.Println("Please center the photo of the QR-code in front" +
"of your web-camera...")
scannedData, err = qr.ReadQRFromCamera()
if err == nil {
break
}
}
clearTerminal()
log.Printf("QR code successfully scanned; the data is: %s\n", scannedData)
}
func clearTerminal() {
c := exec.Command("clear")
c.Stdout = os.Stdout
_ = c.Run()
}

59
qr/qr_read.go Normal file
View File

@ -0,0 +1,59 @@
package qr
import (
"fmt"
"time"
"github.com/makiuchi-d/gozxing"
"github.com/makiuchi-d/gozxing/qrcode"
"gocv.io/x/gocv"
)
const timeToScan = time.Second * 5
func ReadQRFromCamera() (string, error) {
webcam, err := gocv.OpenVideoCapture(0)
if err != nil {
return "", fmt.Errorf("failed to OpenVideoCapture: %w", err)
}
window := gocv.NewWindow("Hello")
defer webcam.Close()
defer window.Close()
img := gocv.NewMat()
tk := time.NewTimer(timeToScan)
// This loop reads an image from the webcam every millisecond
// for 5 seconds. The last image taken will be used as the final
//one.
loop:
for {
select {
case <-tk.C:
break loop
default:
webcam.Read(&img)
window.IMShow(img)
window.WaitKey(1)
}
}
imgObject, err := img.ToImage()
if err != nil {
return "", fmt.Errorf("failed to get image object: %w", err)
}
bmp, err := gozxing.NewBinaryBitmapFromImage(imgObject)
if err != nil {
return "", fmt.Errorf("failed to get NewBinaryBitmapFromImage: %w", err)
}
qrReader := qrcode.NewQRCodeReader()
result, err := qrReader.Decode(bmp, nil)
if err != nil {
return "", fmt.Errorf("failed to decode the QR-code contents: %w", err)
}
return result.String(), err
}

58
qr/qr_show.go Normal file
View File

@ -0,0 +1,58 @@
package qr
import (
"fmt"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"github.com/mattn/go-gtk/glib"
"github.com/mattn/go-gtk/gtk"
encoder "github.com/skip2/go-qrcode"
_ "golang.org/x/image/bmp"
_ "golang.org/x/image/tiff"
)
const tmpImageFile = "/tmp/qr.png"
func ShowQR(data string) error {
err := encoder.WriteFile(data, encoder.Medium, 512, tmpImageFile)
if err != nil {
return fmt.Errorf("failed to encode the data: %w", err)
}
showImage(tmpImageFile)
return nil
}
func showImage(imageFile string) {
gtk.Init(nil)
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
window.SetPosition(gtk.WIN_POS_CENTER)
window.SetTitle("p2p.org QR Viewer")
window.SetIconName("p2p.org QR Viewer")
window.Connect("destroy", func(ctx *glib.CallbackContext) {
gtk.MainQuit()
})
hbox := gtk.NewHBox(false, 1)
hpaned := gtk.NewHPaned()
hbox.Add(hpaned)
frame1 := gtk.NewFrame("QR Code")
framebox1 := gtk.NewHBox(false, 1)
frame1.Add(framebox1)
hpaned.Pack1(frame1, false, false)
image := gtk.NewImageFromFile(imageFile)
framebox1.Add(image)
window.Add(hbox)
imagePixBuffer := image.GetPixbuf()
horizontalSize := imagePixBuffer.GetWidth()
verticalSize := imagePixBuffer.GetHeight()
window.SetSizeRequest(horizontalSize, verticalSize)
window.ShowAll()
gtk.Main()
}