B4X Live Barcode Scanner | Scan QR Codes From Camera Stream
This article is Part 2 in a 3-Part Series.
In the previous article, we created a Dynamsoft Barcode Reader library for B4X. Here, we are gonna use the library to create a barcode scanner which reads barcodes from the camera stream.
You can download the library and learn about its usage in this forum post.
There is an existing B4XPages barcode reader project: Barcode Reader. The project uses the Camera API and Google Play Service’s barcode decoding ability on Android and the iBarcode library which is based on MTBBarcodeScanner for iOS. We can just modify this project to create a cross-platform live barcode scanner using Dynamsoft Barcode Reader. The final result is shown below (the Android version).
For Android, we just use Dynamsoft Barcode Reader in the preview
event to decode camera previews.
#if B4A
Private Sub Camera1_Preview (data() As Byte)
If DateTime.Now > LastPreview + IntervalBetweenPreviewsMs Then
Dim bm As Bitmap=BytesToImage(camEx.PreviewImageToJpeg(data,100))
Dim results As List=reader.decodeImage(bm)
ShowResults(results)
LastPreview = DateTime.Now
End If
End Sub
Public Sub BytesToImage(bytes() As Byte) As Bitmap
Dim In As InputStream
In.InitializeFromBytesArray(bytes, 0, bytes.Length)
Dim bmp As Bitmap
bmp.Initialize2(In)
Return bmp
End Sub
#End If
For iOS, we use LLCamera for camera preview and use Dynamsoft Barcode Reader to decode camera previews.
#If B4I
Private Sub StartCamera
If llc.IsInitialized Then llc.StopPreview
llc.Initialize(pnlPreview, "llc", False)
llc.StartPreview
ConfigureCamera
StartCameraShared
End Sub
Private Sub ConfigureCamera
Try
llc.BeginConfiguration
llc.FlashMode = llc.FLASH_AUTO
llc.PreserveRatio = True
llc.CommitConfiguration
Catch
Log("Error configuring camera: " & LastException.Description)
End Try
End Sub
Private Sub llc_Preview (Image As Bitmap)
If DateTime.Now > LastPreview + IntervalBetweenPreviewsMs Then
Dim results As List=reader.decodeImage(Image)
ShowResults(results)
LastPreview = DateTime.Now
End If
llc.ReleaseFrame(Image)
End Sub
#End If
For desktop, we use B4Jvlc to capture video using web cameras. A timer is used to capture video frames and read barcodes. This approach is similar to the approach used in this article: Barcode Reader with JavaFX and vlcj.
#If B4J
Private Sub StartCamera
If OptionsTextField.Text<>"" Then
getMp.RunMethod("playMedia",Array(MRITextField.Text,getOptions))
Else
vlc.Play(MRITextField.Text)
End If
Timer1.Enabled=True
StartCameraShared
End Sub
Private Sub getOptions As String()
Dim values() As String=Regex.Split(" :",OptionsTextField.Text)
Dim index As Int=0
For Each item As String In values
values(index)=":"&item.Trim()
index=index+1
Next
': :dshow-vdev=USB Camera :dshow-adev= :dshow-size=640x480 :live-caching=300
'dshow://
Return values
End Sub
private Sub getMp As JavaObject
Dim jo As JavaObject=vlc.player
Dim mp As JavaObject=jo.RunMethod("getMp",Null)
Return mp
End Sub
Sub Timer1_Tick
If decoding Then
Return
End If
Dim bufferedImage As JavaObject=getMp.RunMethod("getSnapshot",Null)
If bufferedImage.IsInitialized Then
Dim SwingFXUtils As JavaObject
SwingFXUtils.InitializeStatic("javafx.embed.swing.SwingFXUtils")
Dim image As B4XBitmap = SwingFXUtils.RunMethod("toFXImage",Array(bufferedImage, Null))
decoding=True
ShowResults(reader.decodeImage(image))
decoding=False
End If
End Sub
#End If
Although the camera part is platform-specific, there is still code that can be shared across the three platforms, which is mainly related to UI.
Shared code:
Sub btnStartStop_Click
If Capturing = False Then
StartCamera
Else
StopCamera
End If
End Sub
Private Sub StopCamera
Capturing = False
btnStartStop.Text = "Start"
pnlPreview.Visible = False
#if B4A
If camEx.IsInitialized Then
camEx.Release
End If
#Else If B4i
llc.StopPreview
#Else If B4j
vlc.Pause
Timer1.Enabled=False
#end if
End Sub
Private Sub StartCameraShared
btnStartStop.Text = "Stop"
pnlPreview.Visible = True
Capturing = True
End Sub
Private Sub ShowResults (results As List)
If results.Size=0 Then
lblResult.Text=""
Else
Dim sb As StringBuilder
sb.Initialize
Dim index As Int=0
For Each result As TextResult In results
sb.Append(result.Text)
If index<>results.Size-1 Then
sb.Append(", ")
End If
index=index+1
Next
lblResult.Text = sb.ToString
toast.Show($"Found [Color=Blue][b][plain]${results.Size}[/plain][/b][/Color] barcode(s)"$)
End If
End Sub
Source Code
https://github.com/xulihang/BarcodeReader-B4X
Disclaimer:
The wrappers and sample code on Dynamsoft Codepool are community editions, shared as-is and not fully tested. Dynamsoft is happy to provide technical support for users exploring these solutions but makes no guarantees.