Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(barcode-scanning): incorrect coordinate calculation on iOS #127

Merged
merged 3 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sour-brooms-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@capacitor-mlkit/barcode-scanning': patch
---

fix(ios): incorrect coordinate calculation
1 change: 0 additions & 1 deletion packages/barcode-scanning/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,6 @@ Remove all listeners for this plugin.
| ---------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------- | ----- |
| **`formats`** | <code>BarcodeFormat[]</code> | Improve the speed of the barcode scanner by configuring the barcode formats to scan for. | 0.0.1 |
| **`lensFacing`** | <code><a href="#lensfacing">LensFacing</a></code> | Configure the camera (front or back) to use. | 0.0.1 |
| **`zoomRatio`** | <code>number</code> | The initial zoom ratio of the camera. | 5.4.0 |


#### ReadBarcodesFromImageResult
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,23 +164,31 @@ private static JSONArray convertByteArrayToJsonArray(byte[] bytes) {
}

private static Point[] normalizeCornerPoints(@NonNull Point[] cornerPoints, @NonNull Point imageSize, @NonNull Point screenSize) {
// Log corner points
// Logger.debug("Corner points: " + cornerPoints[0] + ", " + cornerPoints[1] + ", " + cornerPoints[2] + ", " + cornerPoints[3]);
double screenWidth = screenSize.x;
double screenHeight = screenSize.y;
double imageWidth = imageSize.x;
double imageHeight = imageSize.y;
// Swap the image dimensions if the image is in landscape mode
if (screenWidth > screenHeight) {
imageWidth = imageSize.y;
imageHeight = imageSize.x;
}
// Calculate the scale of the image
double scale = Math.max(screenHeight / imageWidth, screenWidth / imageHeight);
// Calculate the invisible area of the image
double invisibleWidth = imageHeight * scale - screenWidth;
double invisibleHeight = imageWidth * scale - screenHeight;
Point[] normalizedCornerPoints = new Point[cornerPoints.length];
for (int i = 0; i < cornerPoints.length; i++) {
// Scale the points and move them to the center of the screen
int x = (int) ((cornerPoints[i].x * scale) - (invisibleWidth / 2));
int y = (int) ((cornerPoints[i].y * scale) - (invisibleHeight / 2));
normalizedCornerPoints[i] = new Point(x, y);
}
// Log normalized corner points
// Logger.debug("Normalized corner points: " + normalizedCornerPoints[0] + ", " + normalizedCornerPoints[1] + ", " + normalizedCornerPoints[2] + ", " + normalizedCornerPoints[3]);
return normalizedCornerPoints;
}
}
41 changes: 31 additions & 10 deletions packages/barcode-scanning/ios/Plugin/BarcodeScannerHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,51 @@ import MLKitBarcodeScanning
// swiftlint:disable cyclomatic_complexity
public class BarcodeScannerHelper {
// swiftlint:disable identifier_name
public static func normalizeCornerPoints(cornerPoints: [NSValue], imageSize: CGSize, scale: CGFloat = UIScreen.main.scale) -> [NSValue] {
let screenSize: CGRect = UIScreen.main.bounds
let imageWidth = imageSize.width
let imageHeight = imageSize.height
public static func normalizeCornerPoints(cornerPoints: [NSValue], imageSize: CGSize, screenSize: CGSize) -> [NSValue] {
// Log corner points
// CAPLog.print("Corner points (\(cornerPoints[0].cgPointValue.x), \(cornerPoints[0].cgPointValue.y)), (\(cornerPoints[1].cgPointValue.x), \(cornerPoints[1].cgPointValue.y)), (\(cornerPoints[2].cgPointValue.x), \(cornerPoints[2].cgPointValue.y)), (\(cornerPoints[3].cgPointValue.x), \(cornerPoints[3].cgPointValue.y))")
let screenWidth = screenSize.width
let screenHeight = screenSize.height
var imageWidth = imageSize.width
var imageHeight = imageSize.height
// Swap the image dimensions if the image is in landscape mode
if screenWidth > screenHeight {
imageWidth = imageSize.height
imageHeight = imageSize.width
}
// Calculate the scale of the image
let scale = max(screenHeight / CGFloat(imageWidth), screenWidth / CGFloat(imageHeight))
// Calculate the invisible area of the image
let invisibleWidth = imageHeight * scale - screenWidth
let invisibleHeight = imageWidth * scale - screenHeight
let isPortrait = UIDevice.current.orientation == .portrait || UIDevice.current.orientation == .portraitUpsideDown
var normalizedCornerPoints = [NSValue]()
for cornerPoint in cornerPoints {
var x = Int((cornerPoint.cgPointValue.x / CGFloat(imageWidth)) * screenSize.width * scale)
var y = Int((cornerPoint.cgPointValue.y / CGFloat(imageHeight)) * screenSize.height * scale)
var x = Int(((cornerPoint.cgPointValue.x * scale) - (invisibleWidth / 2)))
var y = Int(((cornerPoint.cgPointValue.y * scale) - (invisibleHeight / 2)))
if isPortrait {
x = Int((1 - (cornerPoint.cgPointValue.y / CGFloat(imageHeight))) * screenSize.width * scale)
y = Int((cornerPoint.cgPointValue.x / CGFloat(imageWidth)) * screenSize.height * scale)
x = Int((((imageHeight - cornerPoint.cgPointValue.y) * scale) - (invisibleWidth / 2)))
y = Int(((cornerPoint.cgPointValue.x * scale) - (invisibleHeight / 2)))
}
let point = CGPoint(x: x, y: y)
let value = NSValue(cgPoint: point)
normalizedCornerPoints.append(value)
}
// If the image is in portrait mode, the corner points need to be rotated
if isPortrait {
let lastNormalizedCornerPoints = normalizedCornerPoints.removeLast()
normalizedCornerPoints.insert(lastNormalizedCornerPoints, at: 0)
}
// Log normalized corner points
// CAPLog.print("Normalized corner points (\(normalizedCornerPoints[0].cgPointValue.x), \(normalizedCornerPoints[0].cgPointValue.y)), (\(normalizedCornerPoints[1].cgPointValue.x), \(normalizedCornerPoints[1].cgPointValue.y)), (\(normalizedCornerPoints[2].cgPointValue.x), \(normalizedCornerPoints[2].cgPointValue.y)), (\(normalizedCornerPoints[3].cgPointValue.x), \(normalizedCornerPoints[3].cgPointValue.y))")
return normalizedCornerPoints
}

public static func createBarcodeResultForBarcode(_ barcode: Barcode, imageSize: CGSize?, scale: CGFloat = UIScreen.main.scale) -> JSObject {
public static func createBarcodeResultForBarcode(_ barcode: Barcode, imageSize: CGSize?) -> JSObject {
var cornerPointsResult = [[Int]]()
if let cornerPoints = barcode.cornerPoints, let imageSize = imageSize {
let normalizedCornerPoints = normalizeCornerPoints(cornerPoints: cornerPoints, imageSize: imageSize, scale: scale)
let screenSize = CGSize(width: UIScreen.main.bounds.width * UIScreen.main.scale, height: UIScreen.main.bounds.height * UIScreen.main.scale)
let normalizedCornerPoints = normalizeCornerPoints(cornerPoints: cornerPoints, imageSize: imageSize, screenSize: screenSize)
for cornerPoint in normalizedCornerPoints {
var value = [Int]()
value.append(Int(cornerPoint.cgPointValue.x))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public class BarcodeScannerPlugin: CAPPlugin {
}
var barcodeResults = JSArray()
for barcode in barcodes ?? [] {
barcodeResults.append(BarcodeScannerHelper.createBarcodeResultForBarcode(barcode, imageSize: nil, scale: 1))
barcodeResults.append(BarcodeScannerHelper.createBarcodeResultForBarcode(barcode, imageSize: nil))
}
call.resolve([
"barcodes": barcodeResults
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,9 @@ public protocol BarcodeScannerViewDelegate {
private func filterBarcodesOutsideTheDetectionArea(_ barcodes: [Barcode], imageSize: CGSize?, detectionArea: CGRect) -> [Barcode] {
return barcodes.filter { barcode in
if let cornerPoints = barcode.cornerPoints, let imageSize = imageSize {
let screenSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
let normalizedCornerPoints = BarcodeScannerHelper.normalizeCornerPoints(cornerPoints: cornerPoints,
imageSize: imageSize, scale: 1)
imageSize: imageSize, screenSize: screenSize)

let topLeft = normalizedCornerPoints[0].cgPointValue
let topRight = normalizedCornerPoints[1].cgPointValue
Expand Down
Loading