B4X Live Barcode Scanner | Scan QR Codes From Camera Stream

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

Barcode Scanner

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

Getting started with Dynamsoft Barcode Reader

DOWNLOAD THE SDK WITH A 30-DAY LICENSE
REQUEST A 30-DAY LICENSE