二维码开发
二維碼簡(jiǎn)介
二維條碼/二維碼(2-dimensional bar code)是用某種特定的幾何圖形按一定規(guī)律在平面(二維方向上)分布的黑白相間的圖形記錄數(shù)據(jù)符號(hào)信息的;
在代碼編制上巧妙地利用構(gòu)成計(jì)算機(jī)內(nèi)部邏輯基礎(chǔ)的“0”、“1”比特流的概念,使用若干個(gè)與二進(jìn)制相對(duì)應(yīng)的幾何形體來(lái)表示文字?jǐn)?shù)值信息,通過(guò)圖象輸入設(shè)備或光電掃描設(shè)備自動(dòng)識(shí)讀以實(shí)現(xiàn)信息自動(dòng)處理
它具有條碼技術(shù)的一些共性:每種碼制有其特定的字符集;每個(gè)字符占有一定的寬度;具有一定的校驗(yàn)功能等。同時(shí)還具有對(duì)不同行的信息自動(dòng)識(shí)別功能、及處理圖形旋轉(zhuǎn)變化點(diǎn)。
二維碼原理
二維碼本質(zhì)上是一段字符串,可以是一個(gè)網(wǎng)頁(yè)的鏈接,也可以是一句話,電話號(hào)碼,名片等
分析返回結(jié)果,對(duì)結(jié)果進(jìn)行相應(yīng)處理
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}//掃一掃按鈕點(diǎn)擊public void startScan(View view) {//跳到掃描二維碼頁(yè)面Intent intent = new Intent(this, CaptureActivity.class);//startActivity(intent);//跳液面需要返回一個(gè)結(jié)果startActivityForResult(intent, 0);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK) {//獲取解析的數(shù)據(jù)String text = data.getStringExtra("text");System.out.println("MainActivity:" + text);handleResult(text);}}//處理掃描結(jié)果private void handleResult(String text) {//網(wǎng)址: http://www.baidu.com; https://www.xxx.com//tel:110//smsto:13512345678//mailto:xx@163.com//market:////普通字符串if (TextUtils.isEmpty(text)) {return;}if (text.startsWith("http://") || text.startsWith("https://")) {//網(wǎng)址//跳到瀏覽器加載網(wǎng)頁(yè)Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(Uri.parse(text));startActivity(intent);} else if (text.startsWith("tel:")) {//跳到打電話頁(yè)面Intent intent = new Intent(Intent.ACTION_DIAL);intent.setData(Uri.parse(text));startActivity(intent);} else if (text.startsWith("smsto:")) {//跳到發(fā)短信頁(yè)面Intent intent = new Intent(Intent.ACTION_SENDTO);intent.setData(Uri.parse(text));startActivity(intent);} else if (text.startsWith("mailto:")) {//跳到發(fā)郵件頁(yè)面Intent intent = new Intent(Intent.ACTION_SENDTO);intent.setData(Uri.parse(text));startActivity(intent);} else if (text.startsWith("market://")) {//跳到應(yīng)用市場(chǎng)頁(yè)面Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(Uri.parse(text));startActivity(intent);} else {//用彈窗展示信息AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setTitle("掃描結(jié)果:");//標(biāo)題builder.setMessage(text);//內(nèi)容builder.setPositiveButton("確定", null);builder.show();}}}制作帶有圖片生成二維碼
/*** 制作帶有圖片生成二維碼* * @author Administrator* */ public class CodeImage {// 代碼實(shí)現(xiàn)// 圖片寬度的一般private static final int IMAGE_WIDTH = 80;private static final int IMAGE_HEIGHT = 80;private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2;private static final int FRAME_WIDTH = 2;// 二維碼寫(xiě)碼器private static MultiFormatWriter mutiWriter = new MultiFormatWriter();public static void encode(String content, int width, int height, String srcImagePath, String destImagePath) {try {ImageIO.write(genBarcode(content, width, height, srcImagePath), "jpg", new File(destImagePath));} catch (IOException e) {e.printStackTrace();} catch (WriterException e) {e.printStackTrace();}}private static BufferedImage genBarcode(String content, int width, int height, String srcImagePath) throws WriterException, IOException {// 讀取源圖像BufferedImage scaleImage = scale(srcImagePath, IMAGE_WIDTH, IMAGE_HEIGHT, true);int[][] srcPixels = new int[IMAGE_WIDTH][IMAGE_HEIGHT];for (int i = 0; i < scaleImage.getWidth(); i++) {for (int j = 0; j < scaleImage.getHeight(); j++) {srcPixels[i][j] = scaleImage.getRGB(i, j);}}Map<EncodeHintType, Object> hint = new HashMap<EncodeHintType, Object>();hint.put(EncodeHintType.CHARACTER_SET, "utf-8");hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 生成二維碼BitMatrix matrix = mutiWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hint);// 二維矩陣轉(zhuǎn)為一維像素?cái)?shù)組int halfW = matrix.getWidth() / 2;int halfH = matrix.getHeight() / 2;int[] pixels = new int[width * height];for (int y = 0; y < matrix.getHeight(); y++) {for (int x = 0; x < matrix.getWidth(); x++) {// 讀取圖片if (x > halfW - IMAGE_HALF_WIDTH && x < halfW + IMAGE_HALF_WIDTH && y > halfH - IMAGE_HALF_WIDTH && y < halfH + IMAGE_HALF_WIDTH) {pixels[y * width + x] = srcPixels[x - halfW + IMAGE_HALF_WIDTH][y - halfH + IMAGE_HALF_WIDTH];}// 在圖片四周形成邊框else if ((x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW - IMAGE_HALF_WIDTH + FRAME_WIDTH && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH) || (x > halfW + IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH) || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH - IMAGE_HALF_WIDTH + FRAME_WIDTH) || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH && y > halfH + IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)) {pixels[y * width + x] = 0xfffffff;} else {// 此處可以修改二維碼的顏色,可以分別制定二維碼和背景的顏色;pixels[y * width + x] = matrix.get(x, y) ? 0xff000000 : 0xfffffff;}}}BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);image.getRaster().setDataElements(0, 0, width, height, pixels);return image;}/*** 把傳入的原始圖像按高度和寬度進(jìn)行縮放,生成符合要求的圖標(biāo)* * @param srcImageFile* 源文件地址* @param height* 目標(biāo)高度* @param width* 目標(biāo)寬度* @param hasFiller* 比例不對(duì)時(shí)是否需要補(bǔ)白:true為補(bǔ)白; false為不補(bǔ)白;* @throws IOException*/private static BufferedImage scale(String srcImageFile, int height, int width, boolean hasFiller) throws IOException {double ratio = 0.0; // 縮放比例File file = new File(srcImageFile);BufferedImage srcImage = ImageIO.read(file);Image destImage = srcImage.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);// 計(jì)算比例if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {if (srcImage.getHeight() > srcImage.getWidth()) {ratio = (new Integer(height)).doubleValue() / srcImage.getHeight();} else {ratio = (new Integer(width)).doubleValue() / srcImage.getWidth();}AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);destImage = op.filter(srcImage, null);}if (hasFiller) {// 補(bǔ)白BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D graphic = image.createGraphics();graphic.setColor(Color.white);graphic.fillRect(0, 0, width, height);if (width == destImage.getWidth(null))graphic.drawImage(destImage, 0, (height - destImage.getHeight(null)) / 2, destImage.getWidth(null), destImage.getHeight(null), Color.white, null);elsegraphic.drawImage(destImage, (width - destImage.getWidth(null)) / 2, 0, destImage.getWidth(null), destImage.getHeight(null), Color.white, null);graphic.dispose();destImage = image;}return (BufferedImage) destImage;}/*** 程序入口方法 main* * @param args*/public static void main(String[] args) {// 類名CodeImage.方法名encode 傳入相關(guān)參數(shù)// 參數(shù)1 二維碼生成的跳轉(zhuǎn)網(wǎng)站信息 參數(shù)// 2 二維碼生成寬 參數(shù)// 3:二維碼生成高度// 參數(shù)4: 準(zhǔn)備圖片資源磁盤路徑// 參數(shù)5: 生成帶有圖片二維碼 生成目錄CodeImage.encode("http://sh.itcast.cn", 300, 300, "e:/bb/m.jpg", "G:/aa/chuanzhi.jpg");}}二維碼制作類
/*** 二維碼制作類* * @author Administrator* */ public class Code {// 代碼 模板public static int max_data_size_small = 84;public static int max_data_size_large = 500;/*** * @param srcValue* @param qrcodePicfilePath* @return*/public static boolean encode(String srcValue, String qrcodePicfilePath) {// return encode_500(srcValue, qrcodePicfilePath);return encode_84(srcValue, qrcodePicfilePath);}/*** Encoding the information to a QRCode, size of the information must be less than 84 byte.* * @param srcValue* @param qrcodePicfilePath* @return*/public static boolean encode_84(String srcValue, String qrcodePicfilePath) {int MAX_DATA_LENGTH = max_data_size_small; // 限制生成二維碼的數(shù)據(jù)最大大小byte[] d = srcValue.getBytes();int dataLength = d.length;int imageWidth = 113; /* 113是預(yù)先計(jì)算出來(lái)的. 注意:圖像寬度必須比生成的二維碼圖像寬度大,至少相等,否則,二維碼識(shí)別不出來(lái) */int imageHeight = imageWidth;BufferedImage bi = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g = bi.createGraphics();g.setBackground(Color.WHITE);g.clearRect(0, 0, imageWidth, imageHeight);g.setColor(Color.BLACK);if (dataLength > 0 && dataLength <= MAX_DATA_LENGTH) {/* 生成二維碼 */Qrcode qrcode = new Qrcode();qrcode.setQrcodeErrorCorrect('M'); // L, Q, H, 默認(rèn)qrcode.setQrcodeEncodeMode('B'); // A, N, 默認(rèn)qrcode.setQrcodeVersion(5); // 37字節(jié), (37-1)*3+2+3-1+1 = 113boolean[][] b = qrcode.calQrcode(d);int qrcodeDataLen = b.length;for (int i = 0; i < qrcodeDataLen; i++) {for (int j = 0; j < qrcodeDataLen; j++) {if (b[j][i]) {g.fillRect(j * 3 + 2, i * 3 + 2, 3, 3); /** 畫(huà)二維碼圖形, 畫(huà)出的圖形寬度是 ((qrcodeDataLen-1)*3+2) + 3 -1 ; 生成的image的寬度大小必須>=該值,外圍的1個(gè)像素用來(lái)標(biāo)識(shí)此塊區(qū)域?yàn)槎S碼*//** fillRect(int x, int y, int width, int height) 函數(shù)作用: 填充指定的矩形。該矩形左邊和右邊位于 x 和 x + width - 1。頂邊和底邊位于 y 和 y + height - 1。 得到的矩形覆蓋的區(qū)域?qū)挾葹?width 像素,高度為 height 像素。 使用圖形上下文的當(dāng)前顏色填充該矩形。 參數(shù): x - 要填充矩形的 x 坐標(biāo)。 y - 要填充矩形的 y 坐標(biāo)。 width - 要填充矩形的寬度。 height - 要填充矩形的高度。* * 參考:http://bk.chinaar.com/index.php?doc-view-2999*/}}}System.out.println("二維碼數(shù)據(jù)長(zhǎng)度(字節(jié)):" + qrcodeDataLen);} else {System.out.println("Generate QRCode image error! Data size is " + dataLength + ", it is lager than 84 bytes.");return false;}g.dispose();bi.flush();/* generate image */File f = new File(qrcodePicfilePath);String suffix = f.getName().substring(f.getName().indexOf(".") + 1, f.getName().length());try {ImageIO.write(bi, suffix, f); // "png"} catch (IOException ioe) {System.out.println("Generate QRCode image error!" + ioe.getMessage());return false;}return true;}/*** Encoding the information to a QRCode, size of the information must be less tah 500 byte.* * @param srcValue* @param qrcodePicfilePath* @return*/public static boolean encode_500(String srcValue, String qrcodePicfilePath) {int MAX_DATA_LENGTH = max_data_size_large; // 限制生成二維碼的數(shù)據(jù)最大大小. 500字節(jié)的原始數(shù)據(jù), 生成二維碼時(shí), 是89寬度byte[] d = srcValue.getBytes();int dataLength = d.length;int imageWidth = 269; /* 269是預(yù)先計(jì)算出來(lái)的. 注意:圖像寬度必須比生成的二維碼圖像寬度大,至少相等,否則,二維碼識(shí)別不出來(lái) */int imageHeight = imageWidth;BufferedImage bi = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g = bi.createGraphics();g.setBackground(Color.WHITE);g.clearRect(0, 0, imageWidth, imageHeight);g.setColor(Color.BLACK);if (dataLength > 0 && dataLength <= MAX_DATA_LENGTH) {/* 生成二維碼 */Qrcode qrcode = new Qrcode();qrcode.setQrcodeErrorCorrect('M'); // L, Q, H, 默認(rèn)qrcode.setQrcodeEncodeMode('B'); // A, N, 默認(rèn)qrcode.setQrcodeVersion(18); // 0<= version <=40; 89字節(jié),// (89-1)*3+2+3-1+1 = 269boolean[][] b = qrcode.calQrcode(d);int qrcodeDataLen = b.length;for (int i = 0; i < qrcodeDataLen; i++) {for (int j = 0; j < qrcodeDataLen; j++) {if (b[j][i]) {g.fillRect(j * 3 + 2, i * 3 + 2, 3, 3); /** 畫(huà)二維碼圖形, 畫(huà)出的圖形寬度是 ((qrcodeDataLen-1)*3+2) + 3 -1 = 136; 生成的image的寬度大小必須>=(136+1),外圍的1個(gè)像素用來(lái)標(biāo)識(shí)此塊區(qū)域?yàn)槎S碼*//** fillRect(int x, int y, int width, int height) 函數(shù)作用: 填充指定的矩形。該矩形左邊和右邊位于 x 和 x + width - 1。頂邊和底邊位于 y 和 y + height - 1。 得到的矩形覆蓋的區(qū)域?qū)挾葹?width 像素,高度為 height 像素。 使用圖形上下文的當(dāng)前顏色填充該矩形。 參數(shù): x - 要填充矩形的 x 坐標(biāo)。 y - 要填充矩形的 y 坐標(biāo)。 width - 要填充矩形的寬度。 height - 要填充矩形的高度。* * 參考:http://bk.chinaar.com/index.php?doc-view-2999*/}}}System.out.println("二維碼數(shù)據(jù)長(zhǎng)度(字節(jié)):" + qrcodeDataLen);} else {return false;}g.dispose();bi.flush();/* generate image */File f = new File(qrcodePicfilePath);String suffix = f.getName().substring(f.getName().indexOf(".") + 1, f.getName().length());System.out.println(suffix);try {ImageIO.write(bi, suffix, f); // "png"} catch (IOException ioe) {System.out.println("Generate QRCode image error!" + ioe.getMessage());return false;}return true;}/*** 程序入口方法 main* * @param args* @throws Exception*/public static void main(String[] args) throws Exception {// 表示單行注釋 data : 生成二維碼的字符 二維碼信息String data = "http://sh.itcast.cn";// e:/bb/mm.JPG 二維碼生成磁盤路徑Code.encode(data, "e:/bb/mm.JPG");}}二維碼開(kāi)源框架
zxing
Qart
zxing-android-embedded
android-zxingLibrary
總結(jié)