Improve QR reader efficiency and support inverted QR codes

pull/922/head
Alexander Bakker 3 years ago
parent 81d5915969
commit 0909341caa

@ -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'

@ -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,58 +38,47 @@ 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);
ImageProxy.PlaneProxy plane = image.getPlanes()[0];
ByteBuffer buf = plane.getBuffer();
byte[] data = new byte[buf.remaining()];
buf.get(data);
buf.rewind();
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(
data, image.getWidth(), image.getHeight(), 0, 0, image.getWidth(), image.getHeight(), false
data,
plane.getRowStride(),
image.getHeight(),
0,
0,
image.getWidth(),
image.getHeight(),
false
);
QRCodeReader reader = new QRCodeReader();
MultiFormatReader reader = new MultiFormatReader();
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
Result result = reader.decode(bitmap);
Map<DecodeHintType, Object> 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 (ChecksumException | FormatException | NotFoundException ignored) {
} catch (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();
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];
}
}
return cleanData;
}
return data;
}
public interface Listener {
void onQrCodeDetected(Result result);
}

Loading…
Cancel
Save