Zxing 二维码的生成与识别

10 篇文章 0 订阅

Zxing 二维码的生成与识别

    关于二维码的技术有很多SwetakeQRCode、BarCode4j、Zxing.....,这里选择的是google出的zxing方案,

原理请看文章: android二维码实现原理Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果最后有Demo。

    这里在Demo的基础上加上生成二维码功能:

    

import java.io.FileOutputStream;
import java.util.Hashtable;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PointF;
import android.view.Gravity;
import android.view.View.MeasureSpec;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * 二维码生成工具类
 */ 
public class QRCodeUtil { 
	/**
	 * 生成二维码Bitmap, 二维码图片较大时,生成图片、保存文件的时间可能较长,因此需要在子线程中调用 
	 * 如: new Thread(new Runnable() { 
                    @Override 
                    public void run() { 
                        boolean success = QRCodeUtil.createQRImage(contentET.getText().toString().trim(), 800, 800, 
                                addLogoCB.isChecked() ? BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher) : null, 
                                filePath); 
   
                        if (success) { 
                            runOnUiThread(new Runnable() { 
                                @Override 
                                public void run() { 
                                    imageView.setImageBitmap(BitmapFactory.decodeFile(filePath)); 
                                } 
                            }); 
                        } 
                    } 
                }).start(); 
	 *
	 * @param content   内容
	 * @param widthPix  图片宽度
	 * @param heightPix 图片高度
	 * @param logoBm    二维码中心的Logo图标(可以为null)
	 * @param filePath  用于存储二维码图片的文件路径
	 * @return 生成二维码及保存文件是否成功
	 */ 
	public static boolean createQRImage(String content, int widthPix, int heightPix, Bitmap logoBm, String filePath) { 
		try { 
			if (content == null || "".equals(content)) { 
				return false; 
			} 

			//配置参数 
			Hashtable
  
  
   
    hints = new Hashtable
   
   
    
    (); 
			hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); 
			//容错级别 
			hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); 
			//设置空白边距的宽度 
			//            hints.put(EncodeHintType.MARGIN, 2); //default is 4 

			// 图像数据转换,使用了矩阵转换 
			BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix, heightPix, hints); 
			int[] pixels = new int[widthPix * heightPix]; 
			// 下面这里按照二维码的算法,逐个生成二维码的图片, 
			// 两个for循环是图片横列扫描的结果 
			for (int y = 0; y < heightPix; y++) { 
				for (int x = 0; x < widthPix; x++) { 
					if (bitMatrix.get(x, y)) { 
						pixels[y * widthPix + x] = 0xff000000; 
					} else { 
						pixels[y * widthPix + x] = 0xffffffff; 
					} 
				} 
			} 

			// 生成二维码图片的格式,使用ARGB_8888 
			Bitmap bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.ARGB_8888); 
			bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix); 

			if (logoBm != null) { 
				bitmap = addLogo(bitmap, logoBm); 
			} 

			//必须使用compress方法将bitmap保存到文件中再进行读取。直接返回的bitmap是没有任何压缩的,内存消耗巨大! 
			return bitmap != null && bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(filePath)); 
		} catch (Exception e) { 
			e.printStackTrace(); 
		} 

		return false; 
	} 

	/**
	 * 在二维码中间添加Logo图案
	 */ 
	private static Bitmap addLogo(Bitmap src, Bitmap logo) { 
		if (src == null) { 
			return null; 
		} 

		if (logo == null) { 
			return src; 
		} 

		//获取图片的宽高 
		int srcWidth = src.getWidth(); 
		int srcHeight = src.getHeight(); 
		int logoWidth = logo.getWidth(); 
		int logoHeight = logo.getHeight(); 

		if (srcWidth == 0 || srcHeight == 0) { 
			return null; 
		} 

		if (logoWidth == 0 || logoHeight == 0) { 
			return src; 
		} 

		//logo大小为二维码整体大小的1/5 
		float scaleFactor = srcWidth * 1.0f / 5 / logoWidth; 
		Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888); 
		try { 
			Canvas canvas = new Canvas(bitmap); 
			canvas.drawBitmap(src, 0, 0, null); 
			canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2); 
			canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2, null); 
			canvas.save(Canvas.ALL_SAVE_FLAG); 
			canvas.restore(); 
		} catch (Exception e) { 
			bitmap = null; 
			e.getStackTrace(); 
		} 
		return bitmap; 
	} 
	
	/**
	 * 生成条形码
	 * 
	 * @param context
	 * @param contents
	 *            需要生成的内容
	 * @param desiredWidth
	 *            生成条形码的宽带
	 * @param desiredHeight
	 *            生成条形码的高度
	 * @param displayCode
	 *            是否在条形码下方显示内容
	 * @return
	 */
	public static Bitmap creatBarcode(Context context, String contents,
			int desiredWidth, int desiredHeight, boolean displayCode) {
		Bitmap ruseltBitmap = null;
		/**
		 * 图片两端所保留的空白的宽度
		 */
		int marginW = 20;
		/**
		 * 条形码的编码类型
		 */
		BarcodeFormat barcodeFormat = BarcodeFormat.CODE_128;

		if (displayCode) {
			Bitmap barcodeBitmap = encodeAsBitmap(contents, barcodeFormat,
					desiredWidth, desiredHeight);
			Bitmap codeBitmap = creatCodeBitmap(contents, desiredWidth + 2
					* marginW, desiredHeight, context);
			ruseltBitmap = mixtureBitmap(barcodeBitmap, codeBitmap, new PointF(
					0, desiredHeight));
		} else {
			ruseltBitmap = encodeAsBitmap(contents, barcodeFormat,
					desiredWidth, desiredHeight);
		}

		return ruseltBitmap;
	}

	/**
	 * 生成条形码的Bitmap
	 * 
	 * @param contents
	 *            需要生成的内容
	 * @param format
	 *            编码格式
	 * @param desiredWidth
	 * @param desiredHeight
	 * @return
	 * @throws WriterException
	 */
	private static Bitmap encodeAsBitmap(String contents,
			BarcodeFormat format, int desiredWidth, int desiredHeight) {
		final int WHITE = 0xFFFFFFFF;
		final int BLACK = 0xFF000000;

		MultiFormatWriter writer = new MultiFormatWriter();
		BitMatrix result = null;
		try {
			result = writer.encode(contents, format, desiredWidth,
					desiredHeight, null);
		} catch (WriterException e) {
			e.printStackTrace();
		}

		int width = result.getWidth();
		int height = result.getHeight();
		int[] pixels = new int[width * height];
		// All are 0, or black, by default
		for (int y = 0; y < height; y++) {
			int offset = y * width;
			for (int x = 0; x < width; x++) {
				pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
			}
		}

		Bitmap bitmap = Bitmap.createBitmap(width, height,
				Bitmap.Config.ARGB_8888);
		bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return bitmap;
	}

	/**
	 * 生成显示编码的Bitmap
	 * 
	 * @param contents
	 * @param width
	 * @param height
	 * @param context
	 * @return
	 */
	private static Bitmap creatCodeBitmap(String contents, int width,
			int height, Context context) {
		TextView tv = new TextView(context);
		LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		tv.setLayoutParams(layoutParams);
		tv.setText(contents);
		tv.setHeight(height);
		tv.setGravity(Gravity.CENTER_HORIZONTAL);
		tv.setWidth(width);
		tv.setDrawingCacheEnabled(true);
		tv.setTextColor(Color.BLACK);
		tv.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
				MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
		tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());

		tv.buildDrawingCache();
		Bitmap bitmapCode = tv.getDrawingCache();
		return bitmapCode;
	}

	/**
	 * 将两个Bitmap合并成一个
	 * 
	 * @param first
	 * @param second
	 * @param fromPoint
	 *            第二个Bitmap开始绘制的起始位置(相对于第一个Bitmap)
	 * @return
	 */
	private static Bitmap mixtureBitmap(Bitmap first, Bitmap second,
			PointF fromPoint) {
		if (first == null || second == null || fromPoint == null) {
			return null;
		}
		int marginW = 20;
		Bitmap newBitmap = Bitmap.createBitmap(
				first.getWidth() + second.getWidth() + marginW,
				first.getHeight() + second.getHeight(), Config.ARGB_4444);
		Canvas cv = new Canvas(newBitmap);
		cv.drawBitmap(first, marginW, 0, null);
		cv.drawBitmap(second, fromPoint.x, fromPoint.y, null);
		cv.save(Canvas.ALL_SAVE_FLAG);
		cv.restore();

		return newBitmap;
	}
}

   
   
  
  

    

    Demo下载地址:Demo

    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值