Android從圖片獲取二維碼的方法
之前的博客我記得講過(guò)關(guān)于掃描二維碼的內(nèi)容,昨天,組長(zhǎng)讓我不僅可以掃描獲取二維碼,還可以通過(guò)圖片獲取里面的二維碼。比如別人拍了一張二維碼的照片,發(fā)送給你,app應(yīng)該可以獲取圖片的二維碼。
自己在網(wǎng)上查了資料,發(fā)現(xiàn)其實(shí)也很簡(jiǎn)單,用ZXing jar包里的獲取圖片二維碼的QRCodeReader就基本可以了。不過(guò)大部分的內(nèi)容,我自己也不明白,大家如果有興趣,可以自己去查找資料。
1.點(diǎn)擊按鈕后,跳轉(zhuǎn)到相冊(cè),選擇有二維碼的圖片,返回到解析二維碼的界面。這時(shí)通過(guò)返回的URI獲取圖片的路徑。
case CHOOSE_PIC: String[] proj = new String[]{MediaStore.Images.Media.DATA}; Cursor cursor = QRCodeActivity.this.getContentResolver().query(data.getData(), proj, null, null, null); if(cursor.moveToFirst()){ int columnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA); System.out.println(columnIndex); //獲取到用戶選擇的二維碼圖片的絕對(duì)路徑 imgPath = cursor.getString(columnIndex); } cursor.close(); //獲取解析結(jié)果 Result ret = parseQRcodeBitmap(imgPath); if (ret==null){ Toast.makeText(QRCodeActivity.this,getString(R.string.load_two_dimensional_error), Toast.LENGTH_LONG).show(); }else { // Toast.makeText(QRCodeActivity.this,"解析結(jié)果:" + ret.toString(), Toast.LENGTH_LONG).show(); Intent intent = new Intent(); intent.putExtra(Intents.Scan.RESULT, ret.toString()); this.setResult(Activity.RESULT_OK, intent); this.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); finish(); } break;
這個(gè)就是通過(guò)ContentResolver查詢URI獲取圖片的路徑,然后調(diào)用parseQRcodeBitmap(imgPath)獲取圖片的二維碼。
2.通過(guò)圖片路徑進(jìn)行解析圖片,獲取圖片的二維碼值。
//解析二維碼圖片,返回結(jié)果封裝在Result對(duì)象中 private com.google.zxing.Result parseQRcodeBitmap(String bitmapPath){ //解析轉(zhuǎn)換類型UTF-8 Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>(); hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); //獲取到待解析的圖片 BitmapFactory.Options options = new BitmapFactory.Options(); //如果我們把inJustDecodeBounds設(shè)為true,那么BitmapFactory.decodeFile(String path, Options opt) //并不會(huì)真的返回一個(gè)Bitmap給你,它僅僅會(huì)把它的寬,高取回來(lái)給你 options.inJustDecodeBounds = true; //此時(shí)的bitmap是null,這段代碼之后,options.outWidth 和 options.outHeight就是我們想要的寬和高了 Bitmap bitmap = BitmapFactory.decodeFile(bitmapPath,options); //我們現(xiàn)在想取出來(lái)的圖片的邊長(zhǎng)(二維碼圖片是正方形的)設(shè)置為400像素 /** options.outHeight = 400; options.outWidth = 400; options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeFile(bitmapPath, options); */ //以上這種做法,雖然把bitmap限定到了我們要的大小,但是并沒(méi)有節(jié)約內(nèi)存,如果要節(jié)約內(nèi)存,我們還需要使用inSimpleSize這個(gè)屬性 options.inSampleSize = options.outHeight / 400; if(options.inSampleSize <= 0){ options.inSampleSize = 1; //防止其值小于或等于0 } /** * 輔助節(jié)約內(nèi)存設(shè)置 * * options.inPreferredConfig = Bitmap.Config.ARGB_4444; // 默認(rèn)是Bitmap.Config.ARGB_8888 * options.inPurgeable = true; * options.inInputShareable = true; */ options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeFile(bitmapPath, options); //新建一個(gè)RGBLuminanceSource對(duì)象,將bitmap圖片傳給此對(duì)象 RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(bitmap); //將圖片轉(zhuǎn)換成二進(jìn)制圖片 BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(rgbLuminanceSource)); //初始化解析對(duì)象 QRCodeReader reader = new QRCodeReader(); //開(kāi)始解析 Result result = null; try { result = reader.decode(binaryBitmap, hints); } catch (Exception e) { // TODO: handle exception } return result; }
這里首先獲取圖片的bitmap,需要把獲取的bitmap專為一定的大小,通過(guò)options.inSampleSize來(lái)實(shí)現(xiàn),然后通過(guò)
//新建一個(gè)RGBLuminanceSource對(duì)象,將bitmap圖片傳給此對(duì)象 RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(bitmap); //將圖片轉(zhuǎn)換成二進(jìn)制圖片 BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(rgbLuminanceSource)); //初始化解析對(duì)象 QRCodeReader reader = new QRCodeReader();
將bitmap的二維碼轉(zhuǎn)換成圖片,然后又將圖片轉(zhuǎn)成二進(jìn)制圖片,調(diào)用QRCodeReader的result = reader.decode(binaryBitmap, hints);代碼把二進(jìn)制圖片轉(zhuǎn)成二維碼,然后直接獲取返回值的字符串就是二維碼值。
其中用到了一個(gè)自定義的類RGBLuminanceSource,主要功能是將圖片的二維碼內(nèi)容獲取到,把除二維碼的內(nèi)容過(guò)濾,方便接下來(lái)的解析二維碼。
package com.zwcode.p6spro.util; import java.io.FileNotFoundException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import com.google.zxing.LuminanceSource; public class RGBLuminanceSource extends LuminanceSource { private final byte[] luminances; public RGBLuminanceSource(Bitmap bitmap) { super(bitmap.getWidth(), bitmap.getHeight()); //得到圖片的寬高 int width = bitmap.getWidth(); int height = bitmap.getHeight(); //得到圖片的像素 int[] pixels = new int[width * height]; // bitmap.getPixels(pixels, 0, width, 0, 0, width, height); //為了測(cè)量純解碼速度,我們將整個(gè)圖像灰度陣列前面,這是一樣的通道 // YUVLuminanceSource在現(xiàn)實(shí)應(yīng)用。 //得到像素大小的字節(jié)數(shù) luminances = new byte[width * height]; //得到圖片每點(diǎn)像素顏色 for (int y = 0; y < height; y++) { int offset = y * width; for (int x = 0; x < width; x++) { int pixel = pixels[offset + x]; int r = (pixel >> 16) & 0xff; int g = (pixel >> 8) & 0xff; int b = pixel & 0xff; //當(dāng)某一點(diǎn)三種顏色值相同時(shí),相應(yīng)字節(jié)對(duì)應(yīng)空間賦值為其值 if (r == g && g == b) { luminances[offset + x] = (byte) r; } //其它情況字節(jié)空間對(duì)應(yīng)賦值為: else { luminances[offset + x] = (byte) ((r + g + g + b) >> 2); } } } } public RGBLuminanceSource(String path) throws FileNotFoundException { this(loadBitmap(path)); } @Override public byte[] getMatrix() { return luminances; } @Override public byte[] getRow(int arg0, byte[] arg1) { if (arg0 < 0 || arg0 >= getHeight()) { throw new IllegalArgumentException( "Requested row is outside the image: " + arg0); } int width = getWidth(); if (arg1 == null || arg1.length < width) { arg1 = new byte[width]; } System.arraycopy(luminances, arg0 * width, arg1, 0, width); return arg1; } private static Bitmap loadBitmap(String path) throws FileNotFoundException { Bitmap bitmap = BitmapFactory.decodeFile(path); if (bitmap == null) { throw new FileNotFoundException("Couldn't open " + path); } return bitmap; } }
這樣就可以識(shí)別圖片的二維碼了,用這個(gè)功能一定要先導(dǎo)入ZXing jar包,這個(gè)很簡(jiǎn)單,網(wǎng)上有很多介紹,大家自己可以查找一下。
Android 從圖片獲取二維碼就講完了。
就這么簡(jiǎn)單。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android中g(shù)oogle Zxing實(shí)現(xiàn)二維碼與條形碼掃描
- Android二維碼創(chuàng)建實(shí)例
- Android基于zxing的二維碼(網(wǎng)格)掃描 仿支付寶網(wǎng)格掃描
- Android中使用ZXing生成二維碼(支持添加Logo圖案)
- Android利用ZXing掃描二維碼的實(shí)例代碼解析
- Android項(xiàng)目實(shí)戰(zhàn)(二十八):使用Zxing實(shí)現(xiàn)二維碼及優(yōu)化實(shí)例
- Android實(shí)現(xiàn)二維碼掃描和生成的簡(jiǎn)單方法
- Android掃描二維碼時(shí)出現(xiàn)用戶禁止權(quán)限報(bào)錯(cuò)問(wèn)題解決辦法
相關(guān)文章
Android利用ShaderMask實(shí)現(xiàn)花里胡哨的文字特效
我們的?App?大部分時(shí)候的文字都是一種顏色,實(shí)際上,文字的顏色也可以多姿多彩。我們今天就來(lái)介紹一個(gè)能夠輕松實(shí)現(xiàn)文字漸變色的組件?——?ShaderMask,感興趣的可以了解一下2022-12-12Android使用MulticastSocket實(shí)現(xiàn)多點(diǎn)廣播圖片
這篇文章主要為大家詳細(xì)介紹了Android使用MulticastSocket實(shí)現(xiàn)多點(diǎn)廣播圖片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01Android開(kāi)發(fā)中ViewPager實(shí)現(xiàn)多頁(yè)面切換效果
ViewPager用于實(shí)現(xiàn)多頁(yè)面的切換效果,該類存在于Google的兼容包里面,所以在引用時(shí)記得在BuilldPath中加入“Android-support-v4.jar”。具體詳情大家可以參考下本文2016-11-11在Flutter中制作翻轉(zhuǎn)卡片動(dòng)畫(huà)的完整實(shí)例代碼
最近Flutter的勢(shì)頭是越來(lái)越猛了,作為一個(gè)Android程序猿,我自然也是想要趕緊嘗試一把,這篇文章主要給大家介紹了關(guān)于在Flutter中制作翻轉(zhuǎn)卡片動(dòng)畫(huà)的相關(guān)資料,需要的朋友可以參考下2021-10-10Android進(jìn)階之使用時(shí)間戳計(jì)算時(shí)間差
這篇文章主要為大家詳細(xì)介紹了Android進(jìn)階之使用時(shí)間戳計(jì)算時(shí)間差,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12Android 實(shí)現(xiàn)背景圖和狀態(tài)欄融合方法
下面小編就為大家分享一篇Android 實(shí)現(xiàn)背景圖和狀態(tài)欄融合方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01解決Android中自定義DialogFragment解決寬度和高度問(wèn)題
Android中自定義DialogFragment解決寬度和高度問(wèn)題但是我們很多時(shí)候想把DialogFragment的高度固定,那么我們需要設(shè)置DialogFragment的高度,在Fragment的onResume()聲明周期方法中設(shè)置window的寬高即可2017-12-12Android利用listview控件操作SQLite數(shù)據(jù)庫(kù)實(shí)例
我們利用SQLiteOpenHelper類建立一個(gè)數(shù)據(jù)庫(kù),并寫(xiě)好增、刪、查等方法,通過(guò)SimpleCursorAdapter連接listview實(shí)現(xiàn)數(shù)據(jù)庫(kù)的增加、查詢以及長(zhǎng)按刪除的功能。2017-04-04