• <tfoot id="ukgsw"><input id="ukgsw"></input></tfoot>
    
    • 久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
      分享

      安卓實現個性彩色好看的二維碼

       WindySky 2016-03-01

      前言

      二維碼以前也寫過好幾篇,今天姑且是對以前知識的總結,順便復習一下,圣人說過:溫故知新

      還是和以前一樣先看下效果,再來對著代碼講解。

      看效果圖:

      技術分享
      技術分享

      技術分享

      之前呢,也寫過用安卓實現二維碼生成彩色的二維碼帶logo的二維碼,也知道可以使用QRCode和ZXing兩種方式,然后這一篇呢也是寫二維碼使用BarcodeFormat.QR_CODE,主要也是看見很多的非常漂亮的二維碼,這里呢主要模仿qq的二維碼,并且也高仿實現了長按發送給朋友和保存到圖庫的功能,覺得不錯呢就請多支持下,哪里不好呢也可以說出來。好了我們一步一步來。

      第一步:簡單二維碼實現

      先來個最簡單的二維碼:
      技術分享
      看下簡單代碼實現:

       /**
           * 根據指定內容生成自定義寬高的二維碼圖片
           *
           * @param content
           *            需要生成二維碼的內容
           * @param width
           *            二維碼寬度
           * @param height
           *            二維碼高度
           * @throws WriterException
           *             生成二維碼異常
           */
          public static Bitmap makeQRImage(String content, int width, int height)
                  throws WriterException {
              Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
              hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
              // 圖像數據轉換,使用了矩陣轉換
              BitMatrix bitMatrix = new QRCodeWriter().encode(content,
                      BarcodeFormat.QR_CODE, width, height, hints);
              int[] pixels = new int[width * height];
              // 按照二維碼的算法,逐個生成二維碼的圖片,兩個for循環是圖片橫列掃描的結果
              for (int y = 0; y < height; y++) {
                  for (int x = 0; x < width; x++) {
                      if (bitMatrix.get(x, y))//范圍內為黑色的
                          pixels[y * width + x] = 0xff000000;
                      else//其他的地方為白色
                          pixels[y * width + x] = 0xffffffff;
                  }
              }
              // 生成二維碼圖片的格式,使用ARGB_8888
              Bitmap bitmap = Bitmap.createBitmap(width, height,
                      Bitmap.Config.ARGB_8888);
             //設置像素矩陣的范圍
              bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
              return bitmap;
          }

      第二步:簡單二維碼加logo

      接下來給二維碼加logo:(看圖)

      技術分享

       /**
           * 根據指定內容生成自定義寬高的二維碼圖片
           *
           * param logoBm
           *            logo圖標
           * param content
           *            需要生成二維碼的內容
           * param width
           *            二維碼寬度
           * param height
           *            二維碼高度
           * throws WriterException
           *             生成二維碼異常
           */
          public static Bitmap makeQRImage(Bitmap logoBmp, String content,
                                           int QR_WIDTH, int QR_HEIGHT) throws WriterException {
              try {
                  // 圖像數據轉換,使用了矩陣轉換
                  Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
                  hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
                  hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 容錯率
                  hints.put(EncodeHintType.MARGIN, 2); // default is 4
                  hints.put(EncodeHintType.MAX_SIZE, 350);
                  hints.put(EncodeHintType.MIN_SIZE, 100);
                  BitMatrix bitMatrix = new QRCodeWriter().encode(content,
                          BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints);
                  int[] pixels = new int[QR_WIDTH * QR_HEIGHT];
                  for (int y = 0; y < QR_HEIGHT; y++) {
      
                      // 下面這里按照二維碼的算法,逐個生成二維碼的圖片,//兩個for循環是圖片橫列掃描的結果
                      for (int x = 0; x < QR_WIDTH; x++) {
                          if (bitMatrix.get(x, y))
                              pixels[y * QR_WIDTH + x] = 0xff000000;
                          else
                              pixels[y * QR_WIDTH + x] = 0xffffffff;
                      }
                  }
                  // ------------------添加圖片部分------------------//
                  Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT,
                          Bitmap.Config.ARGB_8888);
                  // 設置像素點
                  bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT);
                  // 獲取圖片寬高
                  int logoWidth = logoBmp.getWidth();
                  int logoHeight = logoBmp.getHeight();
                  if (QR_WIDTH == 0 || QR_HEIGHT == 0) {
                      return null;
                  }
                  if (logoWidth == 0 || logoHeight == 0) {
                      return bitmap;
                  }
                  // 圖片繪制在二維碼中央,合成二維碼圖片
                  // logo大小為二維碼整體大小的1/2
                  float scaleFactor = QR_WIDTH * 1.0f / 2 / logoWidth;
                  try {
                      Canvas canvas = new Canvas(bitmap);
                      canvas.drawBitmap(bitmap, 0, 0, null);
                      canvas.scale(scaleFactor, scaleFactor, QR_WIDTH / 2,
                              QR_HEIGHT / 2);
                      canvas.drawBitmap(logoBmp, (QR_WIDTH - logoWidth) / 2,
                              (QR_HEIGHT - logoHeight) /2, null);
                      canvas.save(Canvas.ALL_SAVE_FLAG);
                      canvas.restore();
                      return bitmap;
                  } catch (Exception e) {
                      bitmap = null;
                      e.getStackTrace();
                  }
              } catch (WriterException e) {
                  e.printStackTrace();
              }
              return null;
          }

      上段代碼可以看出要給二維碼圖片中間加logo,但是圖片不能占據整個二維碼圖片的很大一部分。然后還必須設置容錯率:容錯率有M,L,Q,H幾個等級,容錯率越高,二維碼的有效像素點就越多。這里使用小寫的utf-8編碼,大寫會出現]Q2\000026開頭內容,為了好看點還設置了邊距和大小。

      第三步:實現帶logo的彩色二維碼

      接下來我們把黑白矩陣變為彩色矩陣:
      就把

       if (bitMatrix.get(x, y))
                          pixels[y * width + x] = 0xff000000;
                      else
                          pixels[y * width + x] = 0xffffffff;

      替換為:(這里的顏色隨便設置,效果隨便改)

       if (x < QR_WIDTH / 2 && y < QR_HEIGHT / 2) {
                                  pixels[y * QR_WIDTH + x] = 0xFF0094FF;// 藍色
                                  Integer.toHexString(new Random().nextInt());
                              } else if (x < QR_WIDTH / 2 && y > QR_HEIGHT / 2) {
                                  pixels[y * QR_WIDTH + x] = 0xFFFED545;// 黃色
                              } else if (x > QR_WIDTH / 2 && y > QR_HEIGHT / 2) {
                                  pixels[y * QR_WIDTH + x] = 0xFF5ACF00;// 綠色
                              } else {
                                  pixels[y * QR_WIDTH + x] = 0xFF000000;// 黑色
                              }
                          } else {
                              pixels[y * QR_WIDTH + x] = 0xffffffff;// 白色
                          }

      改后的效果:

      技術分享

      第四步:給二維碼加背景

      接下來我們來給二維碼圖片加背景:

      /**
           * 給二維碼圖片加背景
           *
           */
          public static Bitmap addBackground(Bitmap foreground,Bitmap background){
              int bgWidth = background.getWidth();
              int bgHeight = background.getHeight();
              int fgWidth = foreground.getWidth();
              int fgHeight = foreground.getHeight();
              Bitmap newmap = Bitmap
                      .createBitmap(bgWidth, bgHeight, Bitmap.Config.ARGB_8888);
              Canvas canvas = new Canvas(newmap);
              canvas.drawBitmap(background, 0, 0, null);
              canvas.drawBitmap(foreground, (bgWidth - fgWidth) / 2,
                      (bgHeight - fgHeight) *3 / 5+70, null);
              canvas.save(Canvas.ALL_SAVE_FLAG);
              canvas.restore();
              return newmap;
          }

      這樣效果就變為:

      技術分享

      第五步:給二維碼加水印

      然后二維碼的個性化制作就最后一步了:加水印,位置隨便放

       /**
           * 在圖片右下角添加水印
           *
           * @param srcBMP
           *            原圖
           * @param markBMP
           *            水印圖片
           * @return 合成水印后的圖片
           */
          public static Bitmap composeWatermark(Bitmap srcBMP, Bitmap markBMP) {
              if (srcBMP == null) {
                  return null;
              }
              // 創建一個新的和SRC長度寬度一樣的位圖
              Bitmap newb = Bitmap.createBitmap(srcBMP.getWidth(),
                      srcBMP.getHeight(), Bitmap.Config.ARGB_8888);
              Canvas cv = new Canvas(newb);
              // 在 0,0坐標開始畫入原圖
              cv.drawBitmap(srcBMP, 0, 0, null);
              // 在原圖的右下角畫入水印
              cv.drawBitmap(markBMP, srcBMP.getWidth() - markBMP.getWidth()*4/5,
                      srcBMP.getHeight()*2/7 , null);
              // 保存
              cv.save(Canvas.ALL_SAVE_FLAG);
              // 存儲
              cv.restore();
              return newb;
          }

      技術分享
      這里貼下實現二維碼個性化的完整代碼類:

      package com.ry.personalizedcode.uitls;
      
      
      import android.content.Context;
      import android.graphics.Bitmap;
      import android.graphics.BitmapFactory;
      import android.graphics.Canvas;
      
      import com.google.zxing.BarcodeFormat;
      import com.google.zxing.EncodeHintType;
      import com.google.zxing.WriterException;
      import com.google.zxing.common.BitMatrix;
      import com.google.zxing.qrcode.QRCodeWriter;
      import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
      
      import java.util.Hashtable;
      import java.util.Random;
      
      /**
       * Created  on 2016/2/24.
       * 生成二維碼的工具類
       */
      public class MakeQRCodeUtil {
      
      
          /**
           * 根據指定內容生成自定義寬高的二維碼圖片
           *
           * param logoBm
           *            logo圖標
           * param content
           *            需要生成二維碼的內容
           * param width
           *            二維碼寬度
           * param height
           *            二維碼高度
           * throws WriterException
           *             生成二維碼異常
           */
          public static Bitmap makeQRImage(Bitmap logoBmp, String content,
                                           int QR_WIDTH, int QR_HEIGHT) throws WriterException {
              try {
                  // 圖像數據轉換,使用了矩陣轉換
                  Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
                  hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
                  hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 容錯率
                  hints.put(EncodeHintType.MARGIN, 2); // default is 4
                  hints.put(EncodeHintType.MAX_SIZE, 350);
                  hints.put(EncodeHintType.MIN_SIZE, 100);
      
                  BitMatrix bitMatrix = new QRCodeWriter().encode(content,
                          BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints);
                  int[] pixels = new int[QR_WIDTH * QR_HEIGHT];
                  for (int y = 0; y < QR_HEIGHT; y++) {
      
                      // 下面這里按照二維碼的算法,逐個生成二維碼的圖片,//兩個for循環是圖片橫列掃描的結果
                      for (int x = 0; x < QR_WIDTH; x++) {
                          if (bitMatrix.get(x, y)) {
                              if (x < QR_WIDTH / 2 && y < QR_HEIGHT / 2) {
                                  pixels[y * QR_WIDTH + x] = 0xFF0094FF;// 藍色
                                  Integer.toHexString(new Random().nextInt());
                              } else if (x < QR_WIDTH / 2 && y > QR_HEIGHT / 2) {
                                  pixels[y * QR_WIDTH + x] = 0xFFFED545;// 黃色
                              } else if (x > QR_WIDTH / 2 && y > QR_HEIGHT / 2) {
                                  pixels[y * QR_WIDTH + x] = 0xFF5ACF00;// 綠色
                              } else {
                                  pixels[y * QR_WIDTH + x] = 0xFF000000;// 黑色
                              }
      
                          } else {
                              pixels[y * QR_WIDTH + x] = 0xffffffff;// 白色
                          }
      
                      }
                  }
                  // ------------------添加圖片部分------------------//
      
                  Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT,
                          Bitmap.Config.ARGB_8888);
      
                  // 設置像素點
      
                  bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT);
                  // 獲取圖片寬高
                  int logoWidth = logoBmp.getWidth();
                  int logoHeight = logoBmp.getHeight();
      
                  if (QR_WIDTH == 0 || QR_HEIGHT == 0) {
                      return null;
                  }
      
                  if (logoWidth == 0 || logoHeight == 0) {
                      return bitmap;
                  }
      
                  // 圖片繪制在二維碼中央,合成二維碼圖片
                  // logo大小為二維碼整體大小的1/2
                  float scaleFactor = QR_WIDTH * 1.0f / 2 / logoWidth;
                  try {
                      Canvas canvas = new Canvas(bitmap);
                      canvas.drawBitmap(bitmap, 0, 0, null);
                      canvas.scale(scaleFactor, scaleFactor, QR_WIDTH / 2,
                              QR_HEIGHT / 2);
                      canvas.drawBitmap(logoBmp, (QR_WIDTH - logoWidth) / 2,
                              (QR_HEIGHT - logoHeight) /2, null);
                      canvas.save(Canvas.ALL_SAVE_FLAG);
                      canvas.restore();
                      return bitmap;
                  } catch (Exception e) {
                      bitmap = null;
                      e.getStackTrace();
                  }
              } catch (WriterException e) {
                  e.printStackTrace();
              }
      
              return null;
          }
          /**
           * 獲取十六進制的顏色代碼.例如  "#6E36B4" , For HTML ,
           * @return String
           */
          public static String getRandColorCode(){
              String r,g,b;
              Random random = new Random();
              r = Integer.toHexString(random.nextInt(256)).toUpperCase();
              g = Integer.toHexString(random.nextInt(256)).toUpperCase();
              b = Integer.toHexString(random.nextInt(256)).toUpperCase();
      
              r = r.length()==1 ? "0" + r : r ;
              g = g.length()==1 ? "0" + g : g ;
              b = b.length()==1 ? "0" + b : b ;
      
              return r+g+b;
          }
          /**
           * 根據指定內容生成自定義寬高的二維碼圖片
           *
           * @param content
           *            需要生成二維碼的內容
           * @param width
           *            二維碼寬度
           * @param height
           *            二維碼高度
           * @throws WriterException
           *             生成二維碼異常
           */
          public static Bitmap makeQRImage(String content, int width, int height)
                  throws WriterException {
      
      
              Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
              hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
              // 圖像數據轉換,使用了矩陣轉換
              BitMatrix bitMatrix = new QRCodeWriter().encode(content,
                      BarcodeFormat.QR_CODE, width, height, hints);
              int[] pixels = new int[width * height];
              // 按照二維碼的算法,逐個生成二維碼的圖片,兩個for循環是圖片橫列掃描的結果
              for (int y = 0; y < height; y++) {
                  for (int x = 0; x < width; x++) {
                      if (bitMatrix.get(x, y))
                          pixels[y * width + x] = 0xff000000;
                      else
                          pixels[y * width + x] = 0xffffffff;
                  }
              }
              // 生成二維碼圖片的格式,使用ARGB_8888
              Bitmap bitmap = Bitmap.createBitmap(width, height,
                      Bitmap.Config.ARGB_8888);
              bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
              return bitmap;
          }
          /**
           * 從資源文件中獲取圖片
           *
           * @param context
           *            上下文
           * @param drawableId
           *            資源文件id
           * @return
           */
          public static Bitmap gainBitmap(Context context, int drawableId) {
              Bitmap bmp = BitmapFactory.decodeResource(context.getResources(),
                      drawableId);
              return bmp;
          }
          /**
           * 在圖片右下角添加水印
           *
           * @param srcBMP
           *            原圖
           * @param markBMP
           *            水印圖片
           * @return 合成水印后的圖片
           */
          public static Bitmap composeWatermark(Bitmap srcBMP, Bitmap markBMP) {
              if (srcBMP == null) {
                  return null;
              }
              // 創建一個新的和SRC長度寬度一樣的位圖
              Bitmap newb = Bitmap.createBitmap(srcBMP.getWidth(),
                      srcBMP.getHeight(), Bitmap.Config.ARGB_8888);
              Canvas cv = new Canvas(newb);
              // 在 0,0坐標開始畫入原圖
              cv.drawBitmap(srcBMP, 0, 0, null);
              // 在原圖的右下角畫入水印
              cv.drawBitmap(markBMP, srcBMP.getWidth() - markBMP.getWidth()*4/5,
                      srcBMP.getHeight()*2/7 , null);
              // 保存
              cv.save(Canvas.ALL_SAVE_FLAG);
              // 存儲
              cv.restore();
      
              return newb;
          }
          /**
           * 給二維碼圖片加背景
           *
           */
          public static Bitmap addBackground(Bitmap foreground,Bitmap background){
              int bgWidth = background.getWidth();
              int bgHeight = background.getHeight();
              int fgWidth = foreground.getWidth();
              int fgHeight = foreground.getHeight();
              Bitmap newmap = Bitmap
                      .createBitmap(bgWidth, bgHeight, Bitmap.Config.ARGB_8888);
              Canvas canvas = new Canvas(newmap);
              canvas.drawBitmap(background, 0, 0, null);
              canvas.drawBitmap(foreground, (bgWidth - fgWidth) / 2,
                      (bgHeight - fgHeight) *3 / 5+70, null);
              canvas.save(Canvas.ALL_SAVE_FLAG);
              canvas.restore();
      
              return newmap;
          }
      }

      第六步:給二維碼實現長按功能

      最后為了模擬下qq的查看二維碼名片功能,還加了一個長按彈出actionSheet的功能。
      看效果:
      技術分享
      具體的 安卓版actionSheet的實現,前面博客有介紹需要的請移步。
      這里我們先來實現發送給好友功能:(這里就不做第三方的發送)

       private void sendToFriends() {
              Intent intent=new Intent(Intent.ACTION_SEND);
              Uri imageUri=  Uri.parse(Environment.getExternalStorageDirectory()+"/code/qrcode.jpg");
              intent.setType("image/*");
              intent.putExtra(Intent.EXTRA_STREAM, imageUri);
              intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
              startActivity(Intent.createChooser(intent, getTitle()));
          }

      發送給朋友效果圖:

      技術分享
      然后就是要實現保存到本地圖庫的功能:

          /**
           * 先保存到本地再廣播到圖庫
           * */
          public static void saveImageToGallery(Context context, Bitmap bmp) {
              // 首先保存圖片
              File appDir = new File(Environment.getExternalStorageDirectory(),
                      "code");
              if (!appDir.exists()) {
                  appDir.mkdir();
              }
              String fileName = "qrcode.jpg";
              file = new File(appDir, fileName);
              try {
                  FileOutputStream fos = new FileOutputStream(file);
                  bmp.compress(CompressFormat.JPEG, 100, fos);
                  fos.flush();
                  fos.close();
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
              // 其次把文件插入到系統圖庫
              try {
                  MediaStore.Images.Media.insertImage(context.getContentResolver(),   file.getAbsolutePath(), fileName, null);
                  // 最后通知圖庫更新
                  context.sendBroadcast(new Intent(           Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"
                                  + file)));
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              }
          }

      總結:

      這篇說白了就是使用了大量的Canvas和bitmap的處理,然后篇幅也是有點長,看起來也是有點累。要看完整的代碼請自己下載PersonalizedCode.rar。下一篇我準備寫webView中的二維碼圖片長按識別二維碼功能。

        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發表

        請遵守用戶 評論公約

        類似文章 更多

        主站蜘蛛池模板: 亚洲人成电影在线天堂色| 亚洲精品一区二区美女| 蜜芽久久人人超碰爱香蕉| 国产线观看免费观看| 一区二区三区无码免费看| 无套内谢少妇毛片在线| 邻居少妇张开腿让我爽了一夜| 桃子视频在线播放WWW| 噜噜久久噜噜久久鬼88| 波多野结衣乳巨码无在线观看| 无码国产偷倩在线播放| 婷婷综合久久中文字幕蜜桃三电影 | 67194熟妇在线观看线路| 国内大量揄拍人妻精品視頻| 国产午精品午夜福利757视频播放 国产午夜亚洲精品国产成人 | 久久久亚洲欧洲日产国码农村| 男人狂桶女人出白浆免费视频| 巨茎中出肉欲人妻在线视频| 亚洲国产成人无码电影| 免费无码专区毛片高潮喷水| 人妻系列无码专区69影院| 特黄A又粗又大又黄又爽A片| 国产一区二区三区导航| 少妇人妻无码专区视频| 东京热TOKYO综合久久精品| 国产不卡一区二区四区| 日本无遮挡真人祼交视频| 国产午夜福利小视频合集| 人人妻人人狠人人爽天天综合网| 亚洲欧美综合精品二区| 中文字幕乱码一区二区免费| 亚洲乱码日产精品一二三| 女人的天堂A国产在线观看| 日本道精品一区二区三区| 18禁网站免费无遮挡无码中文| 国产亚洲精品AA片在线爽| 在线 | 18精品免费1区2| 精品久久久久久无码专区| 精品久久人人做爽综合| 国产精品久久国产三级国不卡顿| 国产女主播白浆在线看|