下面列出了怎么用com.google.zxing.qrcode.QRCodeReader的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* 解析QR图内容
*
* @param imageView
* @return
*/
public static String readImage(ImageView imageView) {
String content = null;
Map<DecodeHintType, String> hints = new HashMap<>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
// 获得待解析的图片
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
RGBLuminanceSource source = new RGBLuminanceSource(bitmap);
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
try {
Result result = reader.decode(bitmap1, hints);
// 得到解析后的文字
content = result.getText();
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
/**
* 读二维码并输出携带的信息
*/
public static void readQrCode(InputStream inputStream) throws IOException {
//从输入流中获取字符串信息
BufferedImage image = ImageIO.read(inputStream);
//将图像转换为二进制位图源
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
Result result = null;
try {
result = reader.decode(bitmap);
} catch (ReaderException e) {
e.printStackTrace();
}
System.out.println(result.getText());
}
private String decode(byte[] data, int width, int height) {
ScannerManager manager = mManager.get();
if (manager == null) {
return null;
}
Rect rect = manager.getFramingRectInPreview();
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data,
width, height, rect.left, rect.top, rect.right, rect.bottom, false);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
try {
Result result = reader.decode(bitmap, mHints);
return result.getText();
} catch (ReaderException e) {
// Ignore as we will repeatedly decode the preview frame
return null;
}
}
public static String decode(BufferedImage image) {
// convert the image to a binary bitmap source
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
// decode the barcode
QRCodeReader reader = new QRCodeReader();
try {
@SuppressWarnings("rawtypes")
Hashtable hints = new Hashtable();
Result result = reader.decode(bitmap, hints);
return result.getText();
} catch (ReaderException e) {
// the data is improperly formatted
}
return "";
}
public static String decode(BufferedImage image) {
// convert the image to a binary bitmap source
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
// decode the barcode
QRCodeReader reader = new QRCodeReader();
try {
@SuppressWarnings("rawtypes")
Hashtable hints = new Hashtable();
Result result = reader.decode(bitmap, hints);
return result.getText();
} catch (ReaderException e) {
// the data is improperly formatted
}
return "";
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
int previewWidth = camera.getParameters().getPreviewSize().width;
int previewHeight = camera.getParameters().getPreviewSize().height;
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(
data, previewWidth, previewHeight, 0, 0, previewWidth,
previewHeight, false);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Reader reader = new QRCodeReader();
try {
Result result = reader.decode(bitmap);
String text = result.getText();
Intent intent = new Intent();
intent.setData(Uri.parse(text));
setResult(RESULT_OK, intent);
finish();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Not Found",
Toast.LENGTH_SHORT).show();
}
}
public DecodeHandler(BaseScanActivity activity, Map<DecodeHintType, Object> hints) {
/*multiFormatReader = new MultiFormatReader();
multiFormatReader.setHints(hints);
this.activity = activity;*/
this.activity = activity;
mQrCodeReader = new QRCodeReader();
mHintsa = new Hashtable<>();
mHintsa.put(DecodeHintType.CHARACTER_SET, "utf-8");
mHintsa.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
mHintsa.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
}
/**
* Decode the data within the viewfinder rectangle, and time how long it took. For efficiency, reuse the same reader
* objects from one decode to the next.
*/
public static Result decodeImage(byte[] data, int width, int height) {
// 处理
Result result = null;
try {
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
PlanarYUVLuminanceSource source =
new PlanarYUVLuminanceSource(data, width, height, 0, 0, width, height, false);
/**
* HybridBinarizer算法使用了更高级的算法,但使用GlobalHistogramBinarizer识别效率确实比HybridBinarizer要高一些。
*
* GlobalHistogram算法:(http://kuangjianwei.blog.163.com/blog/static/190088953201361015055110/)
*
* 二值化的关键就是定义出黑白的界限,我们的图像已经转化为了灰度图像,每个点都是由一个灰度值来表示,就需要定义出一个灰度值,大于这个值就为白(0),低于这个值就为黑(1)。
* 在GlobalHistogramBinarizer中,是从图像中均匀取5行(覆盖整个图像高度),每行取中间五分之四作为样本;以灰度值为X轴,每个灰度值的像素个数为Y轴建立一个直方图,
* 从直方图中取点数最多的一个灰度值,然后再去给其他的灰度值进行分数计算,按照点数乘以与最多点数灰度值的距离的平方来进行打分,选分数最高的一个灰度值。接下来在这两个灰度值中间选取一个区分界限,
* 取的原则是尽量靠近中间并且要点数越少越好。界限有了以后就容易了,与整幅图像的每个点进行比较,如果灰度值比界限小的就是黑,在新的矩阵中将该点置1,其余的就是白,为0。
*/
BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source));
// BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader2 = new QRCodeReader();
result = reader2.decode(bitmap1, hints);
} catch (ReaderException e) {
}
return result;
}
/**
* Decode the data within the viewfinder rectangle, and time how long it took. For efficiency, reuse the same reader
* objects from one decode to the next.
*/
public static Result decodeImage(byte[] data, int width, int height) {
// 处理
Result result = null;
try {
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
PlanarYUVLuminanceSource source =
new PlanarYUVLuminanceSource(data, width, height, 0, 0, width, height, false);
/**
* HybridBinarizer算法使用了更高级的算法,但使用GlobalHistogramBinarizer识别效率确实比HybridBinarizer要高一些。
*
* GlobalHistogram算法:(http://kuangjianwei.blog.163.com/blog/static/190088953201361015055110/)
*
* 二值化的关键就是定义出黑白的界限,我们的图像已经转化为了灰度图像,每个点都是由一个灰度值来表示,就需要定义出一个灰度值,大于这个值就为白(0),低于这个值就为黑(1)。
* 在GlobalHistogramBinarizer中,是从图像中均匀取5行(覆盖整个图像高度),每行取中间五分之四作为样本;以灰度值为X轴,每个灰度值的像素个数为Y轴建立一个直方图,
* 从直方图中取点数最多的一个灰度值,然后再去给其他的灰度值进行分数计算,按照点数乘以与最多点数灰度值的距离的平方来进行打分,选分数最高的一个灰度值。接下来在这两个灰度值中间选取一个区分界限,
* 取的原则是尽量靠近中间并且要点数越少越好。界限有了以后就容易了,与整幅图像的每个点进行比较,如果灰度值比界限小的就是黑,在新的矩阵中将该点置1,其余的就是白,为0。
*/
BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source));
// BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader2 = new QRCodeReader();
result = reader2.decode(bitmap1, hints);
} catch (ReaderException e) {
}
return result;
}
/**
* Decode the data within the viewfinder rectangle, and time how long it took. For efficiency, reuse the same reader
* objects from one decode to the next.
*/
public static Result decodeImage(byte[] data, int width, int height) {
// 处理
Result result = null;
try {
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
PlanarYUVLuminanceSource source =
new PlanarYUVLuminanceSource(data, width, height, 0, 0, width, height, false);
/**
* HybridBinarizer算法使用了更高级的算法,但使用GlobalHistogramBinarizer识别效率确实比HybridBinarizer要高一些。
*
* GlobalHistogram算法:(http://kuangjianwei.blog.163.com/blog/static/190088953201361015055110/)
*
* 二值化的关键就是定义出黑白的界限,我们的图像已经转化为了灰度图像,每个点都是由一个灰度值来表示,就需要定义出一个灰度值,大于这个值就为白(0),低于这个值就为黑(1)。
* 在GlobalHistogramBinarizer中,是从图像中均匀取5行(覆盖整个图像高度),每行取中间五分之四作为样本;以灰度值为X轴,每个灰度值的像素个数为Y轴建立一个直方图,
* 从直方图中取点数最多的一个灰度值,然后再去给其他的灰度值进行分数计算,按照点数乘以与最多点数灰度值的距离的平方来进行打分,选分数最高的一个灰度值。接下来在这两个灰度值中间选取一个区分界限,
* 取的原则是尽量靠近中间并且要点数越少越好。界限有了以后就容易了,与整幅图像的每个点进行比较,如果灰度值比界限小的就是黑,在新的矩阵中将该点置1,其余的就是白,为0。
*/
BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source));
// BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader2 = new QRCodeReader();
result = reader2.decode(bitmap1, hints);
} catch (ReaderException e) {
}
return result;
}
private static Observable<Result> resolve(LuminanceSource source, boolean failWhenNotFound) {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
try {
return Observable.just(reader.decode(bitmap, TRY_HARDER));
} catch (NotFoundException | ChecksumException | FormatException e) {
if (failWhenNotFound) {
return Observable.error(e);
}
} finally {
reader.reset();
}
return Observable.empty();
}
protected Result scanningImage(String path) {
if (StringUtil.isBlank(path)) {
return null;
}
// DecodeHintType 和EncodeHintType
Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); // 设置二维码内容的编码
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 先获取原大小
scanBitmap = BitmapFactory.decodeFile(path, options);
options.inJustDecodeBounds = false; // 获取新的大小
int sampleSize = (int) (options.outHeight / (float) 200);
if (sampleSize <= 0)
sampleSize = 1;
options.inSampleSize = sampleSize;
scanBitmap = BitmapFactory.decodeFile(path, options);
int width = scanBitmap.getWidth(), height = scanBitmap.getHeight();
int[] pixels = new int[width * height];
scanBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
scanBitmap.recycle();
scanBitmap = null;
RGBLuminanceSource source = new RGBLuminanceSource(width, height, pixels);
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
try {
return reader.decode(bitmap1, hints);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 解码 QRCode 图片,解析出其内容
*
* @param imageURI QRCode 图片 URI
* @return 解析后的内容
* @throws IOException
*/
public static String decodeQRCodeImage(URI imageURI) throws IOException {
BufferedImage bufferedImage = ImageReader.readImage(imageURI);
LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
try {
Result result = reader.decode(bitmap);
return result.getText();
} catch (ReaderException e) {
e.printStackTrace();
}
return "";
}
public static String getStringFromQRCode(String path) {
String httpString = null;
Bitmap bmp = convertToBitmap(path);
byte[] data = getYUV420sp(bmp.getWidth(), bmp.getHeight(), bmp);
// 处理
try {
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
// hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data,
bmp.getWidth(),
bmp.getHeight(),
0, 0,
bmp.getWidth(),
bmp.getHeight(),
false);
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader2= new QRCodeReader();
Result result = reader2.decode(bitmap1, hints);
httpString = result.getText();
} catch (Exception e) {
e.printStackTrace();
}
bmp.recycle();
bmp = null;
return httpString;
}
/**
* 直接识别二维码位图
*
* @param bitmap 二维码位图
* @return 二维码包含的内容
*/
public static String recognizeQrCode(Bitmap bitmap)
{
if (bitmap == null)
return null;
Hashtable<DecodeHintType, String> hints = new Hashtable<>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); // 设置二维码内容的编码
//获取图片的像素存入到数组
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
RGBLuminanceSource source = new RGBLuminanceSource(bitmap.getWidth(), bitmap.getHeight(), pixels);
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
try
{
Result result = reader.decode(bitmap1, hints);
if (reader == null)
{
return null;
} else
{
String str = result.toString();
boolean ISO = Charset.forName("ISO-8859-1").newEncoder().canEncode(str);
if (ISO)
str = new String(str.getBytes("ISO-8859-1"), "GB2312");
return str;
}
} catch (Exception e)
{
Log.e("QrCodeHelper", "recognizeQrCode fail:" + e.toString());
}
return null;
}
@Test
public void testQRWorks() throws Exception {
HttpGet getRequest = new HttpGet(httpServerUrl + clientPair.token + "/qr");
String cloneToken;
try (CloseableHttpResponse response = httpclient.execute(getRequest)) {
assertEquals(200, response.getStatusLine().getStatusCode());
assertEquals("image/png", response.getFirstHeader("Content-Type").getValue());
byte[] data = EntityUtils.toByteArray(response.getEntity());
assertNotNull(data);
//get the data from the input stream
BufferedImage image = ImageIO.read(new ByteArrayInputStream(data));
//convert the image to a binary bitmap source
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
Result result = reader.decode(bitmap);
String resultString = result.getText();
assertTrue(resultString.startsWith("blynk://token/clone/"));
assertTrue(resultString.endsWith("?server=127.0.0.1&port=10443"));
cloneToken = resultString.substring(
resultString.indexOf("blynk://token/clone/") + "blynk://token/clone/".length(),
resultString.indexOf("?server=127.0.0.1&port=10443"));
assertEquals(32, cloneToken.length());
}
clientPair.appClient.send("getProjectByCloneCode " + cloneToken);
DashBoard dashBoard = clientPair.appClient.parseDash(1);
assertEquals("My Dashboard", dashBoard.name);
}
public CameraScanActivity(int type) {
super();
CameraController.getInstance().initCamera(() -> {
if (cameraView != null) {
cameraView.initCamera();
}
});
currentType = type;
if (currentType == TYPE_QR) {
qrReader = new QRCodeReader();
//visionQrReader = new BarcodeDetector.Builder(ApplicationLoader.applicationContext).setBarcodeFormats(Barcode.QR_CODE).build();
}
}
/**
* 读取二维码
* @param file 二维码源
* @throws Exception
*/
private static void readCode(File file) throws Exception{
BufferedImage encodedBufferedImage = ImageIO.read(file) ;
LuminanceSource source = new BufferedImageLuminanceSource(encodedBufferedImage);
Result result = new QRCodeReader().decode(new BinaryBitmap(new HybridBinarizer(source)));
System.out.println(result.getText());
}
public CameraScanActivity(int type) {
super();
CameraController.getInstance().initCamera(() -> {
if (cameraView != null) {
cameraView.initCamera();
}
});
currentType = type;
if (currentType == TYPE_QR) {
qrReader = new QRCodeReader();
visionQrReader = new BarcodeDetector.Builder(ApplicationLoader.applicationContext).setBarcodeFormats(Barcode.QR_CODE).build();
}
}
private String decode(final byte[] imageBytes) throws IOException, NotFoundException, ChecksumException, FormatException {
BinaryBitmap bitmap = readToBitmap(imageBytes);
return new QRCodeReader().decode(bitmap).getText();
}
/**
* This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
* to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
* is important for performance in continuous scan clients.
*
* @param hints The set of hints to use for subsequent calls to decode(image)
*/
public void setHints(Map<DecodeHintType,?> hints) {
this.hints = hints;
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
@SuppressWarnings("unchecked")
Collection<BarcodeFormat> formats =
hints == null ? null : (Collection<BarcodeFormat>) hints.get(DecodeHintType.POSSIBLE_FORMATS);
Collection<Reader> readers = new ArrayList<>();
if (formats != null) {
boolean addOneDReader =
formats.contains(BarcodeFormat.UPC_A) ||
formats.contains(BarcodeFormat.UPC_E) ||
formats.contains(BarcodeFormat.EAN_13) ||
formats.contains(BarcodeFormat.EAN_8) ||
formats.contains(BarcodeFormat.CODABAR) ||
formats.contains(BarcodeFormat.CODE_39) ||
formats.contains(BarcodeFormat.CODE_93) ||
formats.contains(BarcodeFormat.CODE_128) ||
formats.contains(BarcodeFormat.ITF) ||
formats.contains(BarcodeFormat.RSS_14) ||
formats.contains(BarcodeFormat.RSS_EXPANDED);
// Put 1D readers upfront in "normal" mode
if (addOneDReader && !tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
if (formats.contains(BarcodeFormat.QR_CODE)) {
readers.add(new QRCodeReader());
}
// At end in "try harder" mode
if (addOneDReader && tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
if (readers.isEmpty()) {
if (!tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
readers.add(new QRCodeReader());
if (tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
this.readers = readers.toArray(new Reader[readers.size()]);
}
/**
* This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
* to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
* is important for performance in continuous scan clients.
*
* @param hints The set of hints to use for subsequent calls to decode(image)
*/
public void setHints(Map<DecodeHintType,?> hints) {
this.hints = hints;
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
@SuppressWarnings("unchecked")
Collection<BarcodeFormat> formats =
hints == null ? null : (Collection<BarcodeFormat>) hints.get(DecodeHintType.POSSIBLE_FORMATS);
Collection<Reader> readers = new ArrayList<>();
if (formats != null) {
boolean addOneDReader =
formats.contains(BarcodeFormat.UPC_A) ||
formats.contains(BarcodeFormat.UPC_E) ||
formats.contains(BarcodeFormat.EAN_13) ||
formats.contains(BarcodeFormat.EAN_8) ||
formats.contains(BarcodeFormat.CODABAR) ||
formats.contains(BarcodeFormat.CODE_39) ||
formats.contains(BarcodeFormat.CODE_93) ||
formats.contains(BarcodeFormat.CODE_128) ||
formats.contains(BarcodeFormat.ITF) ||
formats.contains(BarcodeFormat.RSS_14) ||
formats.contains(BarcodeFormat.RSS_EXPANDED);
// Put 1D readers upfront in "normal" mode
if (addOneDReader && !tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
if (formats.contains(BarcodeFormat.QR_CODE)) {
readers.add(new QRCodeReader());
}
// At end in "try harder" mode
if (addOneDReader && tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
if (readers.isEmpty()) {
if (!tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
readers.add(new QRCodeReader());
if (tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
this.readers = readers.toArray(new Reader[readers.size()]);
}
/**
* This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
* to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
* is important for performance in continuous scan clients.
*
* @param hints The set of hints to use for subsequent calls to decode(image)
*/
public void setHints(Map<DecodeHintType,?> hints) {
this.hints = hints;
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
@SuppressWarnings("unchecked")
Collection<BarcodeFormat> formats =
hints == null ? null : (Collection<BarcodeFormat>) hints.get(DecodeHintType.POSSIBLE_FORMATS);
Collection<Reader> readers = new ArrayList<>();
if (formats != null) {
boolean addOneDReader =
formats.contains(BarcodeFormat.UPC_A) ||
formats.contains(BarcodeFormat.UPC_E) ||
formats.contains(BarcodeFormat.EAN_13) ||
formats.contains(BarcodeFormat.EAN_8) ||
formats.contains(BarcodeFormat.CODABAR) ||
formats.contains(BarcodeFormat.CODE_39) ||
formats.contains(BarcodeFormat.CODE_93) ||
formats.contains(BarcodeFormat.CODE_128) ||
formats.contains(BarcodeFormat.ITF) ||
formats.contains(BarcodeFormat.RSS_14) ||
formats.contains(BarcodeFormat.RSS_EXPANDED);
// Put 1D readers upfront in "normal" mode
if (addOneDReader && !tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
if (formats.contains(BarcodeFormat.QR_CODE)) {
readers.add(new QRCodeReader());
}
// At end in "try harder" mode
if (addOneDReader && tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
if (readers.isEmpty()) {
if (!tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
readers.add(new QRCodeReader());
if (tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
this.readers = readers.toArray(new Reader[readers.size()]);
}
public static Observable<Result> scanFromPicture(String path) {
return Observable.fromCallable(() -> {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
options.inSampleSize = calculateInSampleSize(options, QR_CODE_IN_SAMPLE_LENGTH,
QR_CODE_IN_SAMPLE_LENGTH);
options.inJustDecodeBounds = false;
int[] pixels = null;
QRCodeReader reader = new QRCodeReader();
int retryTimes = 0;
Result result = null;
while (result == null && retryTimes < MAX_RETRY_TIMES) {
Bitmap picture = BitmapFactory.decodeFile(path, options);
int width = picture.getWidth();
int height = picture.getHeight();
if (pixels == null) {
pixels = new int[picture.getWidth() * picture.getHeight()];
}
picture.getPixels(pixels, 0, width, 0, 0, width, height);
picture.recycle();
LuminanceSource source = new RGBLuminanceSource(width, height, pixels);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
result = reader.decode(bitmap, TRY_HARDER);
} catch (NotFoundException | ChecksumException | FormatException ignored) {
retryTimes++;
options.inSampleSize *= 2;
}
}
reader.reset();
return result;
}).flatMap(result -> {
if (result == null) {
return Observable.error(NotFoundException.getNotFoundInstance());
}
return Observable.just(result);
});
}
/**
* This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
* to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
* is important for performance in continuous scan clients.
*
* @param hints The set of hints to use for subsequent calls to decode(image)
*/
public void setHints(Map<DecodeHintType,?> hints) {
this.hints = hints;
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
@SuppressWarnings("unchecked")
Collection<BarcodeFormat> formats =
hints == null ? null : (Collection<BarcodeFormat>) hints.get(DecodeHintType.POSSIBLE_FORMATS);
Collection<Reader> readers = new ArrayList<>();
if (formats != null) {
boolean addOneDReader =
formats.contains(BarcodeFormat.UPC_A) ||
formats.contains(BarcodeFormat.UPC_E) ||
formats.contains(BarcodeFormat.EAN_13) ||
formats.contains(BarcodeFormat.EAN_8) ||
formats.contains(BarcodeFormat.CODABAR) ||
formats.contains(BarcodeFormat.CODE_39) ||
formats.contains(BarcodeFormat.CODE_93) ||
formats.contains(BarcodeFormat.CODE_128) ||
formats.contains(BarcodeFormat.ITF) ||
formats.contains(BarcodeFormat.RSS_14) ||
formats.contains(BarcodeFormat.RSS_EXPANDED);
// Put 1D readers upfront in "normal" mode
if (addOneDReader && !tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
if (formats.contains(BarcodeFormat.QR_CODE)) {
readers.add(new QRCodeReader());
}
if (formats.contains(BarcodeFormat.DATA_MATRIX)) {
readers.add(new DataMatrixReader());
}
if (formats.contains(BarcodeFormat.AZTEC)) {
readers.add(new AztecReader());
}
if (formats.contains(BarcodeFormat.PDF_417)) {
readers.add(new PDF417Reader());
}
if (formats.contains(BarcodeFormat.MAXICODE)) {
readers.add(new MaxiCodeReader());
}
// At end in "try harder" mode
if (addOneDReader && tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
if (readers.isEmpty()) {
if (!tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
readers.add(new QRCodeReader());
readers.add(new DataMatrixReader());
readers.add(new AztecReader());
readers.add(new PDF417Reader());
readers.add(new MaxiCodeReader());
if (tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
this.readers = readers.toArray(new Reader[readers.size()]);
}
@ReactMethod
public void decode(String path, Callback callback) {
Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); // 设置二维码内容的编码
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 先获取原大小
options.inJustDecodeBounds = false; // 获取新的大小
int sampleSize = (int) (options.outHeight / (float) 200);
if (sampleSize <= 0)
sampleSize = 1;
options.inSampleSize = sampleSize;
Bitmap scanBitmap = null;
if (path.startsWith("http://")||path.startsWith("https://")) {
scanBitmap = this.getbitmap(path);
} else {
scanBitmap = BitmapFactory.decodeFile(path, options);
}
if (scanBitmap == null) {
callback.invoke("cannot load image");
return;
}
int[] intArray = new int[scanBitmap.getWidth()*scanBitmap.getHeight()];
scanBitmap.getPixels(intArray, 0, scanBitmap.getWidth(), 0, 0, scanBitmap.getWidth(), scanBitmap.getHeight());
RGBLuminanceSource source = new RGBLuminanceSource(scanBitmap.getWidth(), scanBitmap.getHeight(), intArray);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
try {
Result result = reader.decode(bitmap, hints);
if (result == null) {
callback.invoke("image format error");
} else {
callback.invoke(null, result.toString());
}
} catch (Exception e) {
callback.invoke("decode error");
}
}
/**
* This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
* to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
* is important for performance in continuous scan clients.
*
* @param hints The set of hints to use for subsequent calls to decode(image)
*/
public void setHints(Map<DecodeHintType,?> hints) {
this.hints = hints;
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
@SuppressWarnings("unchecked")
Collection<BarcodeFormat> formats =
hints == null ? null : (Collection<BarcodeFormat>) hints.get(DecodeHintType.POSSIBLE_FORMATS);
Collection<Reader> readers = new ArrayList<Reader>();
if (formats != null) {
boolean addOneDReader =
formats.contains(BarcodeFormat.UPC_A) ||
formats.contains(BarcodeFormat.UPC_E) ||
formats.contains(BarcodeFormat.EAN_13) ||
formats.contains(BarcodeFormat.EAN_8) ||
formats.contains(BarcodeFormat.CODABAR) ||
formats.contains(BarcodeFormat.CODE_39) ||
formats.contains(BarcodeFormat.CODE_93) ||
formats.contains(BarcodeFormat.CODE_128) ||
formats.contains(BarcodeFormat.ITF) ||
formats.contains(BarcodeFormat.RSS_14) ||
formats.contains(BarcodeFormat.RSS_EXPANDED);
// Put 1D readers upfront in "normal" mode
if (addOneDReader && !tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
if (formats.contains(BarcodeFormat.QR_CODE)) {
readers.add(new QRCodeReader());
}
if (formats.contains(BarcodeFormat.DATA_MATRIX)) {
readers.add(new DataMatrixReader());
}
if (formats.contains(BarcodeFormat.AZTEC)) {
readers.add(new AztecReader());
}
if (formats.contains(BarcodeFormat.PDF_417)) {
readers.add(new PDF417Reader());
}
if (formats.contains(BarcodeFormat.MAXICODE)) {
readers.add(new MaxiCodeReader());
}
// At end in "try harder" mode
if (addOneDReader && tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
if (readers.isEmpty()) {
if (!tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
readers.add(new QRCodeReader());
readers.add(new DataMatrixReader());
readers.add(new AztecReader());
readers.add(new PDF417Reader());
readers.add(new MaxiCodeReader());
if (tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
this.readers = readers.toArray(new Reader[readers.size()]);
}
/**
* This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
* to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
* is important for performance in continuous scan clients.
*
* @param hints The set of hints to use for subsequent calls to decode(image)
*/
public void setHints(Map<DecodeHintType,?> hints) {
this.hints = hints;
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
@SuppressWarnings("unchecked")
Collection<BarcodeFormat> formats =
hints == null ? null : (Collection<BarcodeFormat>) hints.get(DecodeHintType.POSSIBLE_FORMATS);
Collection<Reader> readers = new ArrayList<Reader>();
if (formats != null) {
boolean addOneDReader =
formats.contains(BarcodeFormat.UPC_A) ||
formats.contains(BarcodeFormat.UPC_E) ||
formats.contains(BarcodeFormat.EAN_13) ||
formats.contains(BarcodeFormat.EAN_8) ||
formats.contains(BarcodeFormat.CODABAR) ||
formats.contains(BarcodeFormat.CODE_39) ||
formats.contains(BarcodeFormat.CODE_93) ||
formats.contains(BarcodeFormat.CODE_128) ||
formats.contains(BarcodeFormat.ITF) ||
formats.contains(BarcodeFormat.RSS_14) ||
formats.contains(BarcodeFormat.RSS_EXPANDED);
// Put 1D readers upfront in "normal" mode
if (addOneDReader && !tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
if (formats.contains(BarcodeFormat.QR_CODE)) {
readers.add(new QRCodeReader());
}
if (formats.contains(BarcodeFormat.DATA_MATRIX)) {
readers.add(new DataMatrixReader());
}
if (formats.contains(BarcodeFormat.AZTEC)) {
readers.add(new AztecReader());
}
if (formats.contains(BarcodeFormat.PDF_417)) {
readers.add(new PDF417Reader());
}
if (formats.contains(BarcodeFormat.MAXICODE)) {
readers.add(new MaxiCodeReader());
}
// At end in "try harder" mode
if (addOneDReader && tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
if (readers.isEmpty()) {
if (!tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
readers.add(new QRCodeReader());
readers.add(new DataMatrixReader());
readers.add(new AztecReader());
readers.add(new PDF417Reader());
readers.add(new MaxiCodeReader());
if (tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
this.readers = readers.toArray(new Reader[readers.size()]);
}
@SuppressLint("StaticFieldLeak")
private void scanImage(final Uri uri) {
if (progressDialog != null) return;
progressDialog = new ProgressDialogBuilder(this)
.setTitle(R.string.please_wait)
.setMessage(R.string.qr_scan_processing)
.setCancelable(false)
.show();
new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... voids) {
UniFile file = UniFile.fromUri(QRCodeScanActivity.this, uri);
if (file == null) return null;
// ZXing can't process large image
Bitmap bitmap = BitmapUtils.decodeStream(new UniFileInputStreamPipe(file), 1024, 1024);
if (bitmap == null) return null;
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int[] pixels = new int[width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
bitmap.recycle();
int[] newPixels = null;
for (int i = 0; i < 4; i++) {
if (i > 0) {
newPixels = BitmapUtils.rotate(pixels, width, height, newPixels);
int temp = width;
width = height;
height = temp;
int[] tempPixels = pixels;
pixels = newPixels;
newPixels = tempPixels;
}
RGBLuminanceSource source = new RGBLuminanceSource(width, height, pixels);
final HybridBinarizer hybBin = new HybridBinarizer(source);
final BinaryBitmap bBitmap = new BinaryBitmap(hybBin);
QRCodeReader reader = new QRCodeReader();
Map<DecodeHintType, Boolean> hints = new HashMap<>();
try {
return reader.decode(bBitmap, hints).getText();
} catch (NotFoundException | FormatException | ChecksumException e) {
// Try PURE_BARCODE
hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
reader.reset();
try {
return reader.decode(bBitmap, hints).getText();
} catch (NotFoundException | FormatException | ChecksumException ee) {
// pass
}
}
}
return null;
}
@Override
protected void onPostExecute(String text) {
if (progressDialog != null) {
progressDialog.dismiss();
progressDialog = null;
}
if (text != null) {
processCookieText(text);
} else {
Toast.makeText(QRCodeScanActivity.this, R.string.qr_scan_invalid, Toast.LENGTH_SHORT).show();
}
}
}.execute();
}
/**
* This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
* to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
* is important for performance in continuous scan clients.
*
* @param hints The set of hints to use for subsequent calls to decode(image)
*/
public void setHints(Map<DecodeHintType,?> hints) {
this.hints = hints;
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
@SuppressWarnings("unchecked")
Collection<BarcodeFormat> formats =
hints == null ? null : (Collection<BarcodeFormat>) hints.get(DecodeHintType.POSSIBLE_FORMATS);
Collection<Reader> readers = new ArrayList<>();
if (formats != null) {
boolean addOneDReader =
formats.contains(BarcodeFormat.UPC_A) ||
formats.contains(BarcodeFormat.UPC_E) ||
formats.contains(BarcodeFormat.EAN_13) ||
formats.contains(BarcodeFormat.EAN_8) ||
formats.contains(BarcodeFormat.CODABAR) ||
formats.contains(BarcodeFormat.CODE_39) ||
formats.contains(BarcodeFormat.CODE_93) ||
formats.contains(BarcodeFormat.CODE_128) ||
formats.contains(BarcodeFormat.ITF) ||
formats.contains(BarcodeFormat.RSS_14) ||
formats.contains(BarcodeFormat.RSS_EXPANDED);
// Put 1D readers upfront in "normal" mode
if (addOneDReader && !tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
if (formats.contains(BarcodeFormat.QR_CODE)) {
readers.add(new QRCodeReader());
}
if (formats.contains(BarcodeFormat.DATA_MATRIX)) {
readers.add(new DataMatrixReader());
}
if (formats.contains(BarcodeFormat.AZTEC)) {
readers.add(new AztecReader());
}
if (formats.contains(BarcodeFormat.PDF_417)) {
readers.add(new PDF417Reader());
}
if (formats.contains(BarcodeFormat.MAXICODE)) {
readers.add(new MaxiCodeReader());
}
// At end in "try harder" mode
if (addOneDReader && tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
if (readers.isEmpty()) {
if (!tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
readers.add(new QRCodeReader());
readers.add(new DataMatrixReader());
readers.add(new AztecReader());
readers.add(new PDF417Reader());
readers.add(new MaxiCodeReader());
if (tryHarder) {
readers.add(new MultiFormatOneDReader(hints));
}
}
this.readers = readers.toArray(new Reader[readers.size()]);
}