二维码开发

本文介绍了二维码的基本概念,包括其二维条码原理和数据表示方式。接着,详细讲述了二维码的使用,如解析结果并处理,以及如何制作包含图片的二维码。同时,推荐了几个二维码制作的开源框架,如zxing、Qart和zxing-android-embedded。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二维码简介

二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;

在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理

它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化点。

二维码原理

二维码本质上是一段字符串,可以是一个网页的链接,也可以是一句话,电话号码,名片等

分析返回结果,对结果进行相应处理

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    //扫一扫按钮点击
    public void startScan(View view) {
        //跳到扫描二维码页面
        Intent intent = new Intent(this, CaptureActivity.class);
        //startActivity(intent);
        //跳液面需要返回一个结果
        startActivityForResult(intent, 0);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == RESULT_OK) {
            //获取解析的数据
            String text = data.getStringExtra("text");
            System.out.println("MainActivity:" + text);

            handleResult(text);
        }

    }

    //处理扫描结果
    private void handleResult(String text) {
        //网址: 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://")) {
            //网址
            //跳到浏览器加载网页
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setData(Uri.parse(text));
            startActivity(intent);
        } else if (text.startsWith("tel:")) {
            //跳到打电话页面
            Intent intent = new Intent(Intent.ACTION_DIAL);
            intent.setData(Uri.parse(text));
            startActivity(intent);
        } else if (text.startsWith("smsto:")) {
            //跳到发短信页面
            Intent intent = new Intent(Intent.ACTION_SENDTO);
            intent.setData(Uri.parse(text));
            startActivity(intent);
        } else if (text.startsWith("mailto:")) {
            //跳到发邮件页面
            Intent intent = new Intent(Intent.ACTION_SENDTO);
            intent.setData(Uri.parse(text));
            startActivity(intent);
        } else if (text.startsWith("market://")) {
            //跳到应用市场页面
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setData(Uri.parse(text));
            startActivity(intent);
        } else {
            //用弹窗展示信息
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("扫描结果:");//标题
            builder.setMessage(text);//内容
            builder.setPositiveButton("确定", null);

            builder.show();
        }

    }

}

制作带有图片生成二维码

/**
 * 制作带有图片生成二维码
 * 
 * @author Administrator
 * 
 */
public class CodeImage {
    // 代码实现
    // 图片宽度的一般
    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;

    // 二维码写码器
    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);

        // 二维矩阵转为一维像素数组
        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;
    }

    /**
     * 把传入的原始图像按高度和宽度进行缩放,生成符合要求的图标
     * 
     * @param srcImageFile
     *            源文件地址
     * @param height
     *            目标高度
     * @param width
     *            目标宽度
     * @param hasFiller
     *            比例不对时是否需要补白:true为补白; false为不补白;
     * @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);
        // 计算比例
        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) {// 补白
            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);
            else
                graphic.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 传入相关参数
        // 参数1 二维码生成的跳转网站信息 参数
        // 2 二维码生成宽 参数
        // 3:二维码生成高度
        // 参数4: 准备图片资源磁盘路径
        // 参数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; // 限制生成二维码的数据最大大小
        byte[] d = srcValue.getBytes();
        int dataLength = d.length;
        int imageWidth = 113; /* 113是预先计算出来的. 注意:图像宽度必须比生成的二维码图像宽度大,至少相等,否则,二维码识别不出来 */
        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, 默认
            qrcode.setQrcodeEncodeMode('B'); // A, N, 默认
            qrcode.setQrcodeVersion(5); // 37字节, (37-1)*3+2+3-1+1 = 113
            boolean[][] 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); /*
                                                                 * 画二维码图形, 画出的图形宽度是 ((qrcodeDataLen-1)*3+2) + 3 -1 ; 生成的image的宽度大小必须>=该值,外围的1个像素用来标识此块区域为二维码
                                                                 */
                        /*
                         * fillRect(int x, int y, int width, int height) 函数作用: 填充指定的矩形。该矩形左边和右边位于 x 和 x + width - 1。顶边和底边位于 y 和 y + height - 1。 得到的矩形覆盖的区域宽度为 width 像素,高度为 height 像素。 使用图形上下文的当前颜色填充该矩形。 参数: x - 要填充矩形的 x 坐标。 y - 要填充矩形的 y 坐标。 width - 要填充矩形的宽度。 height - 要填充矩形的高度。
                         * 
                         * 参考:http://bk.chinaar.com/index.php?doc-view-2999
                         */
                    }
                }
            }
            System.out.println("二维码数据长度(字节):" + 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; // 限制生成二维码的数据最大大小. 500字节的原始数据, 生成二维码时, 是89宽度
        byte[] d = srcValue.getBytes();
        int dataLength = d.length;
        int imageWidth = 269; /* 269是预先计算出来的. 注意:图像宽度必须比生成的二维码图像宽度大,至少相等,否则,二维码识别不出来 */
        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, 默认
            qrcode.setQrcodeEncodeMode('B'); // A, N, 默认
            qrcode.setQrcodeVersion(18); // 0<= version <=40; 89字节,
                                            // (89-1)*3+2+3-1+1 = 269
            boolean[][] 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); /*
                                                                 * 画二维码图形, 画出的图形宽度是 ((qrcodeDataLen-1)*3+2) + 3 -1 = 136; 生成的image的宽度大小必须>=(136+1),外围的1个像素用来标识此块区域为二维码
                                                                 */
                        /*
                         * fillRect(int x, int y, int width, int height) 函数作用: 填充指定的矩形。该矩形左边和右边位于 x 和 x + width - 1。顶边和底边位于 y 和 y + height - 1。 得到的矩形覆盖的区域宽度为 width 像素,高度为 height 像素。 使用图形上下文的当前颜色填充该矩形。 参数: x - 要填充矩形的 x 坐标。 y - 要填充矩形的 y 坐标。 width - 要填充矩形的宽度。 height - 要填充矩形的高度。
                         * 
                         * 参考:http://bk.chinaar.com/index.php?doc-view-2999
                         */
                    }
                }
            }
            System.out.println("二维码数据长度(字节):" + 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");
    }

}

二维码开源框架

zxing
Qart
zxing-android-embedded
android-zxingLibrary

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值