Motivation
Sometimes you have packages/pallets with several codes, with the Scandit Barcode Scanner you can scan all the codes or just a subset at the same time, saving time and money. To do this you have to use the Matrix Scan option.
Matrix Scan
Matrix Scan track recognized barcodes over time by making it easier to use.
Enabling Matrix Scan
To implement Matrix Scanning
- Enable matrix scanning in the scan settings by setting SBSScanSettings::matrixScanEnabled to
YES
. - Set the maximum number of codes to be decoded every frame through SBSScanSettings::maxNumberOfCodesPerFrame to something higher than 1, depending on the environment of the codes it is a good idea to set it higher than the number of codes that you actually want to scan.
- Change the GUI style through SBSOverlayController::guiStyle to
SBSGuiStyleMatrixScan
.
One of the use cases of Matrix Scan is to detect when the specified number of expected codes has been decoded by the scanner. To implement this scenario:
- In the barcodePicker:didScan: (SBSScanDelegate-p) method, wait until the number of expected codes have been decoded, then store the codes and pause/stop the session. If you pause and plan to resume but want to start a new session, make sure that you clear the session first (see code snippet below).
At this point you can start the barcode picker and any recognized barcodes of the enabled symbologies will be highlighted by a filled green rectangle. Barcodes that have been localized but not recognized will be highlighted by a green border.
Objective-C:
Swift:
Rejecting unwanted codes
Like normal scanning Matrix Scanning provides you the option to reject codes. Just like for normal scanning rejected codes are not added to the scan session and do not provide any feedback like vibrating or beeping. In Matrix Scan the rejected codes are still drawn on the screen but in a different color. This gives the user visual feedback that a certain code is not the one you are looking for. To implement rejection
- Set a
SBSProcessFrameDelegate
on the picker SBSBarcodePicker::processFrameDelegate. - In the barcodePicker:didProcessFrame:session: (SBSProcessFrameDelegate-p) method you fetch the currently tracked barcodes from the session through SBSScanSession::trackedCodes.
- Once you've checked the tracked codes for their symbologies and/or data you can reject them through rejectTrackedCode: (SBSScanSession).
Note: Rejecting in the barcodePicker:didScan: (SBSScanDelegate-p) method is not allowed.
Objective-C:
Swift:
Providing your own visualization
MatrixScan returns the locations of tracked barcodes with every processed frame. This allows you to replace the default visualization with your own. For example, you might want to overlay the barcodes with images of the products they refer to. To add your own visualization, you have two options:
- Take advantage of the Advanced Overlays Framework, which is the high-level API for the MatrixScan that was designed and developed specifically for this purpose.
- Implement your own mechanism for drawing and animating the visualizations for every tracked barcode.
Both of these approaches are described in the sections below. Note: The Advanced Overlays Framework is the easier and preferred method of implementing custom visualizations, as it takes care of all the animations for you and should cover the majority of use cases.
With the Advanced Overlays Framework
As mentioned before, the Advanced Overlays Framework (AOF) is a high-level interface designed to simplify the process of applying your own visualizations to MatrixScan. This framework consists of several classes and protocols that can be imported with the <ScanditBarcodeScanner/SBSMatrixScan.h>
header.
Below there are some implementation guidelines that will help you better understand how the AOF works and how it should be used.
The main component of the AOF is the SBSMatrixScanHandler
class. In order to use the framework you will have to instantiate it. It requires an instance of SBSBarcodePicker
and an instance of SBSMatrixScanDelegate
(more on that later). To add a custom overlay to be drawn on top of the tracked barcodes, simply call the addOverlay: (SBSMatrixScanHandler) method. The SBSMatrixScanOverlay
can only be conformed by UIView
subclasses.
To make things easier, the AOF provides two concrete implementations of the SBSMatrixScanOverlay
: SBSSimpleMatrixScanOverlay
and SBSViewBasedMatrixScanOverlay
. The first one enables you to draw colorful, rectangle overlays on top of the tracked barcodes - similar to the way MatrixScan without AOF Framework works, except with SBSSimpleMatrixScanOverlay
you get more control over the color of every tracked barcode. The SBSViewBasedMatrixScanOverlay
, on the other hand, uses UIView
class instances as visualizations for all of the tracked barcodes.
The AOF Framework doesn't limit you to just one custom overlay - you can call the addOverlay: (SBSMatrixScanHandler) method multiple times. You just have to remember, that the overlays will be displayed on top of each other in the order of their addition. Note: Adding too many overlays can decrease the performance and responsiveness of your app, especially on low-end devices.
Finally, you can manipulate the behavior of the AOF Framework with the SBSMatrixScanDelegate
, mentioned earlier in this section. This protocol consists of 2 delegate methods. The matrixScanHandler:didProcessFrame: (SBSMatrixScanDelegate-p) method will be called every time a SBSFrame
is being processed by the SBSMatrixScanHandler
. The matrixScanHandler:shouldRejectCode: (SBSMatrixScanDelegate-p) method, on the other hand, can be used to define an extra condition for rejecting a barcode (this is analogous to the code rejection described in the Rejecting unwanted codes section).
SBSSimpleMatrixScanOverlay
Swift:
The SBSSimpleMatrixScanOverlayDelegate
also provides you with a simpleMatrixScanOverlay:didTapCode:withIdentifier: (SBSSimpleMatrixScanOverlayDelegate-p) method, that will be called every time the given augmentation is touched, so that you can perform some extra action at that time e.g.:
Swift:
SBSViewBasedMatrixScanOverlay
Similarly to the SBSSimpleMatrixScanOverlay
, the SBSViewBasedMatrixScanOverlay
is also equipped with a listener: SBSViewBasedMatrixScanOverlayDelegate
. It provides two useful callbacks for manipulating the view augmentation of each barcode: SBSViewBasedMatrixScanOverlay::viewBasedMatrixScanOverlay:viewForCode:withIdentifier: and SBSViewBasedMatrixScanOverlay::viewBasedMatrixScanOverlay:offsetForCode:withIdentifier:. Example: Swift:
Note: In the documentation a visualization for a single barcode is also often called an augmentation. Therefore, a SBSViewBasedMatrixScanOverlay
consists of multiple augmentations (one augmentation for every tracked barcode currently within the camera feed).
Without the Advanced Overlays Framework
If for some reason the Advanced Overlays Framework doesn't suit your needs, you can still replace the default visualization with your own, by following the steps described below
- Set a
SBSProcessFrameDelegate
on the picker SBSBarcodePicker::processFrameDelegate. - In the barcodePicker:didProcessFrame:session: (SBSProcessFrameDelegate-p) method you fetch the currently tracked barcodes from the session through rejectTrackedCode: (SBSScanSession). The object is a dictionary with keys of type
NSNumber
which identify theSBSTrackedCode
s over different frames. - Compare the keys of the current frame with the one from the previous one and change your visualization accordingly. Instead of using SBSTrackedCode::location which gives you the exact location of the barcode in the frame, you should generally use SBSTrackedCode::predictedLocation which gives you a predicted location for the barcode. Using the predicted location avoids lagging behind the camera feed that is displayed.
- There are some state transitions where animating from the previous location of a tracked barcode to its current position can end up with weird artifacts as the edge ordering of the location is not stable. If your visualization depends on the edge ordering make sure that you query SBSTrackedCode::shouldAnimateFromPreviousToNextState before animating. The default visualization makes use of this as it draws the location with all four edges and therefore depends on the edge ordering, if the order of the edges were to change it is possible that an animation would flip the visualization which is not what happens to the actual barcode. However, a visualization that just draws something in the center of the location does not depend on the edge ordering and can ignore SBSTrackedCode::shouldAnimateFromPreviousToNextState.
- When animating your visualization take into consideration SBSTrackedCode::deltaTimeForPrediction which tells you how long it will take the code to move to the predicted location. This time generally is about as long as it will take the barcode picker to process the next frame, giving you a new predicted location right as your previous animation is coming to an end.
Important: The coordinates you get back from SBSTrackedCode::location and SBSTrackedCode::predictedLocation are in the coordinate system of the processed frame. To visualize them on top of the picker's camera feed you have to convert them to the picker's coordinate system which you do by calling SBSBarcodePicker::convertPointToPickerCoordinates.
Important: Don't forget that the barcodePicker:didProcessFrame:session: (SBSProcessFrameDelegate-p) method is not called on the mainThread, you have to switch to it to change the UI.
Objective-C:
Swift: