Merge pull request #792 from ziegenberg/790-qr-code-not-found-in-image-file

fix QR code not found in image file
This commit is contained in:
Jakob Nixdorf 2021-03-17 06:36:58 +01:00 committed by GitHub
commit 780b880c9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 24 deletions

View file

@ -72,12 +72,7 @@ dependencies {
implementation "com.github.aakira:expandable-layout:1.6.0" implementation "com.github.aakira:expandable-layout:1.6.0"
implementation "com.heinrichreimersoftware:material-intro:2.0.0" implementation "com.heinrichreimersoftware:material-intro:2.0.0"
implementation("com.journeyapps:zxing-android-embedded:4.1.0") { transitive = false } implementation("com.journeyapps:zxing-android-embedded:4.1.0") { transitive = false }
implementation('com.google.zxing:core') { implementation('com.google.zxing:core:3.4.1')
version {
strictly '[3.3, 3.4[' // Keep pinned below 3.4 to support SDK versions below 24
prefer '3.3.0'
}
}
implementation "com.vanniktech:vntnumberpickerpreference:1.0.0" implementation "com.vanniktech:vntnumberpickerpreference:1.0.0"
implementation "me.zhanghai.android.materialprogressbar:library:1.6.1" implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
implementation "org.sufficientlysecure:openpgp-api:12.0" implementation "org.sufficientlysecure:openpgp-api:12.0"

View file

@ -1,3 +1,26 @@
/*
* Copyright (C) 2017-2020 Jakob Nixdorf
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.shadowice.flocke.andotp.Utilities; package org.shadowice.flocke.andotp.Utilities;
import android.content.Context; import android.content.Context;
@ -6,21 +29,44 @@ import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.widget.Toast; import android.widget.Toast;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap; import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException; import com.google.zxing.ChecksumException;
import com.google.zxing.DecodeHintType;
import com.google.zxing.FormatException; import com.google.zxing.FormatException;
import com.google.zxing.LuminanceSource; import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException; import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource; import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Reader; import com.google.zxing.ReaderException;
import com.google.zxing.Result; import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer; import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.R;
import java.io.IOException; import java.io.IOException;
import java.util.EnumMap;
import java.util.Map;
import java.util.Vector;
public class ScanQRCodeFromFile { public class ScanQRCodeFromFile {
private static final Map<DecodeHintType, Object> HINTS;
private static final Map<DecodeHintType, Object> HINTS_HARDER;
static {
Vector<BarcodeFormat> barcodeFormats = new Vector<>();
barcodeFormats.add(BarcodeFormat.QR_CODE);
HINTS = new EnumMap<>(DecodeHintType.class);
HINTS.put(DecodeHintType.POSSIBLE_FORMATS, barcodeFormats);
HINTS_HARDER = new EnumMap<>(HINTS);
HINTS_HARDER.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
}
public static String scanQRImage(Context context, Uri uri) { public static String scanQRImage(Context context, Uri uri) {
//Check if external storage is accessible //Check if external storage is accessible
if (!Tools.isExternalStorageReadable()) { if (!Tools.isExternalStorageReadable()) {
@ -30,35 +76,60 @@ public class ScanQRCodeFromFile {
//Get image in bytes //Get image in bytes
byte[] imageInBytes; byte[] imageInBytes;
try { try {
imageInBytes = StorageAccessHelper.loadFile(context,uri); imageInBytes = StorageAccessHelper.loadFile(context, uri);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
Toast.makeText(context,R.string.toast_file_load_error,Toast.LENGTH_LONG).show(); Toast.makeText(context, R.string.toast_file_load_error, Toast.LENGTH_LONG).show();
return null; return null;
} }
Bitmap bMap = BitmapFactory.decodeByteArray(imageInBytes,0,imageInBytes.length); Bitmap bMap = BitmapFactory.decodeByteArray(imageInBytes, 0, imageInBytes.length);
String contents = null; String contents = null;
int[] intArray = new int[bMap.getWidth()*bMap.getHeight()]; int[] intArray = new int[bMap.getWidth() * bMap.getHeight()];
bMap.getPixels(intArray, 0, bMap.getWidth(), 0, 0, bMap.getWidth(), bMap.getHeight()); bMap.getPixels(intArray, 0, bMap.getWidth(), 0, 0, bMap.getWidth(), bMap.getHeight());
LuminanceSource source = new RGBLuminanceSource(bMap.getWidth(), bMap.getHeight(), intArray); LuminanceSource source = new RGBLuminanceSource(bMap.getWidth(), bMap.getHeight(), intArray);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Reader reader = new MultiFormatReader();
//Try finding QR code Result result = null;
QRCodeReader reader = new QRCodeReader();
ReaderException savedException = null;
try { try {
Result result = reader.decode(bitmap); //Try finding QR code
result = reader.decode(bitmap, HINTS);
contents = result.getText(); contents = result.getText();
} catch (NotFoundException e) { } catch (ReaderException re) {
e.printStackTrace(); savedException = re;
Toast.makeText(context,R.string.toast_qr_error,Toast.LENGTH_LONG).show(); }
if (contents == null) {
try {
//Try finding QR code really hard
result = reader.decode(bitmap, HINTS_HARDER);
contents = result.getText();
} catch (ReaderException re) {
savedException = re;
}
}
if (contents == null) {
try {
throw savedException == null ? NotFoundException.getNotFoundInstance() : savedException;
} catch (ChecksumException e) { } catch (ChecksumException e) {
e.printStackTrace(); e.printStackTrace();
Toast.makeText(context,R.string.toast_qr_checksum_exception,Toast.LENGTH_LONG).show(); Toast.makeText(context, R.string.toast_qr_checksum_exception, Toast.LENGTH_LONG).show();
} catch (FormatException e) { } catch (FormatException e) {
e.printStackTrace(); e.printStackTrace();
Toast.makeText(context,R.string.toast_qr_format_error,Toast.LENGTH_LONG).show(); Toast.makeText(context, R.string.toast_qr_format_error, Toast.LENGTH_LONG).show();
} catch (ReaderException e) { // Including NotFoundException
e.printStackTrace();
Toast.makeText(context, R.string.toast_qr_error, Toast.LENGTH_LONG).show();
} }
}
//Return QR code (if found) //Return QR code (if found)
return contents; return contents;
} }