diff --git a/app/build.gradle b/app/build.gradle index da0f1794..87e05758 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -163,7 +163,7 @@ dependencies { implementation "com.google.guava:guava:${guavaVersion}-android" implementation 'com.google.android.material:material:1.5.0' implementation 'com.google.protobuf:protobuf-javalite:3.19.4' - implementation 'com.google.zxing:core:3.4.1' + implementation 'com.google.zxing:core:3.5.0' implementation "com.mikepenz:iconics-core:3.2.5" implementation 'com.mikepenz:material-design-iconic-typeface:2.2.0.5@aar' implementation 'com.nulab-inc:zxcvbn:1.6.0' diff --git a/app/src/main/java/com/beemdevelopment/aegis/helpers/QrCodeAnalyzer.java b/app/src/main/java/com/beemdevelopment/aegis/helpers/QrCodeAnalyzer.java index b85ff402..e1bbee30 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/helpers/QrCodeAnalyzer.java +++ b/app/src/main/java/com/beemdevelopment/aegis/helpers/QrCodeAnalyzer.java @@ -1,5 +1,7 @@ package com.beemdevelopment.aegis.helpers; +import static android.graphics.ImageFormat.YUV_420_888; + import android.os.Handler; import android.os.Looper; import android.util.Log; @@ -9,20 +11,19 @@ import androidx.annotation.NonNull; import androidx.camera.core.ImageAnalysis; import androidx.camera.core.ImageProxy; +import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; -import com.google.zxing.ChecksumException; -import com.google.zxing.FormatException; +import com.google.zxing.DecodeHintType; +import com.google.zxing.MultiFormatReader; import com.google.zxing.NotFoundException; import com.google.zxing.PlanarYUVLuminanceSource; import com.google.zxing.Result; import com.google.zxing.common.HybridBinarizer; -import com.google.zxing.qrcode.QRCodeReader; import java.nio.ByteBuffer; - -import static android.graphics.ImageFormat.YUV_420_888; -import static android.graphics.ImageFormat.YUV_422_888; -import static android.graphics.ImageFormat.YUV_444_888; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; public class QrCodeAnalyzer implements ImageAnalysis.Analyzer { private static final String TAG = QrCodeAnalyzer.class.getSimpleName(); @@ -37,56 +38,45 @@ public class QrCodeAnalyzer implements ImageAnalysis.Analyzer { @Override public void analyze(@NonNull ImageProxy image) { int format = image.getFormat(); - if (format != YUV_420_888 && format != YUV_422_888 && format != YUV_444_888) { - Log.e(TAG, String.format("Expected YUV format, got %d instead", format)); + if (format != YUV_420_888) { + Log.e(TAG, String.format("Unexpected YUV image format: %d", format)); image.close(); return; } - byte[] data = getLuminancePlaneData(image); - PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource( - data, image.getWidth(), image.getHeight(), 0, 0, image.getWidth(), image.getHeight(), false - ); - - QRCodeReader reader = new QRCodeReader(); - BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); - try { - Result result = reader.decode(bitmap); - if (_listener != null) { - new Handler(Looper.getMainLooper()).post(() -> _listener.onQrCodeDetected(result)); - } - } catch (ChecksumException | FormatException | NotFoundException ignored) { - - } finally { - image.close(); - } - } - - private static byte[] getLuminancePlaneData(ImageProxy image) { ImageProxy.PlaneProxy plane = image.getPlanes()[0]; ByteBuffer buf = plane.getBuffer(); byte[] data = new byte[buf.remaining()]; buf.get(data); buf.rewind(); - int width = image.getWidth(); - int height = image.getHeight(); - int rowStride = plane.getRowStride(); - int pixelStride = plane.getPixelStride(); + PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource( + data, + plane.getRowStride(), + image.getHeight(), + 0, + 0, + image.getWidth(), + image.getHeight(), + false + ); - if (width != rowStride || pixelStride != 1) { - // remove padding from the Y plane data - byte[] cleanData = new byte[width * height]; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - cleanData[y * width + x] = data[y * rowStride + x * pixelStride]; - } + MultiFormatReader reader = new MultiFormatReader(); + BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); + try { + Map hints = new HashMap<>(); + hints.put(DecodeHintType.POSSIBLE_FORMATS, Collections.singletonList(BarcodeFormat.QR_CODE)); + hints.put(DecodeHintType.ALSO_INVERTED, true); + + Result result = reader.decode(bitmap, hints); + if (_listener != null) { + new Handler(Looper.getMainLooper()).post(() -> _listener.onQrCodeDetected(result)); } + } catch (NotFoundException ignored) { - return cleanData; + } finally { + image.close(); } - - return data; } public interface Listener {