Java实现生成和解码二维码具体操作步骤

QR码的使用越来越多,可以在很多地方见着,比如火车票、推广产品上等,以下将介绍如何用Java生成QR码以及解码QR码。

1、涉及开源项目

ZXing :一个开源Java类库用于解析多种格式的1D/2D条形码。目标是能够对QR编码、Data Matrix、UPC的1D条形码进行解码。 其提供了多种平台下的客户端包括:J2ME、J2SE和Android。---用来解码QRcode

d-project:Kazuhiko Arase的个人项目(他具体是谁不清楚,日本的),提供丰富的配置参数,非常灵活---用来生成QR code

2、效果图:

生成QR code


解码QR code

3、使用d-project生成QRcdoe

    1)将com.d_project.qrcode.jar引入工程

    2)QRcodeAction代码:


public void generate(RequestContext rc)
002	            throws UnsupportedEncodingException, IOException, ServletException {
003	                //待转数据
004	        String data = rc.param("data", "http://osctools.net/qr");
005	                //输出图片类型
006	                String output = rc.param("output", "image/jpeg");
007	 
008	        int type = rc.param("type", 4);
009	        if (type < 0 || 10 < type) {
010	            return;
011	        }
012	 
013	        int margin = rc.param("margin", 10);
014	        if (margin < 0 || 32 < margin) {
015	            return;
016	        }
017	 
018	        int cellSize = rc.param("size", 4);
019	        if (cellSize < 1 || 4 < cellSize) {
020	            return;
021	        }
022	 
023	        int errorCorrectLevel = 0;
024	 
025	        try {
026	            errorCorrectLevel = parseErrorCorrectLevel(rc,
027	                    rc.param("error", "H"));
028	        } catch (Exception e) {
029	            return;
030	        }
031	 
032	        com.d_project.qrcode.QRCode qrcode = null;
033	        try {
034	            qrcode = getQRCode(data, type, errorCorrectLevel);
035	        } catch (Exception e) {
036	            return;
037	        }
038	 
039	        if ("image/jpeg".equals(output)) {
040	 
041	            BufferedImage image = qrcode.createImage(cellSize, margin);
042	 
043	            rc.response().setContentType("image/jpeg");
044	 
045	            OutputStream out = new BufferedOutputStream(rc.response()
046	                    .getOutputStream());
047	 
048	            try {
049	                ImageIO.write(image, "jpeg", out);
050	            } finally {
051	                out.close();
052	            }
053	 
054	        } else if ("image/png".equals(output)) {
055	 
056	            BufferedImage image = qrcode.createImage(cellSize, margin);
057	 
058	            rc.response().setContentType("image/png");
059	 
060	            OutputStream out = new BufferedOutputStream(rc.response()
061	                    .getOutputStream());
062	 
063	            try {
064	                ImageIO.write(image, "png", out);
065	            } finally {
066	                out.close();
067	            }
068	 
069	        } else if ("image/gif".equals(output)) {
070	 
071	            GIFImage image = createGIFImage(qrcode, cellSize, margin);
072	 
073	            rc.response().setContentType("image/gif");
074	 
075	            OutputStream out = new BufferedOutputStream(rc.response()
076	                    .getOutputStream());
077	 
078	            try {
079	                image.write(out);
080	            } finally {
081	                out.close();
082	            }
083	 
084	        } else {
085	            return;
086	        }
087	 
088	    }
089	 
090	    private static int parseErrorCorrectLevel(RequestContext rc, String ecl) {
091	        if ("L".equals(ecl)) {
092	            return ErrorCorrectLevel.L;
093	        } else if ("Q".equals(ecl)) {
094	            return ErrorCorrectLevel.Q;
095	        } else if ("M".equals(ecl)) {
096	            return ErrorCorrectLevel.M;
097	        } else if ("H".equals(ecl)) {
098	            return ErrorCorrectLevel.H;
099	        } else {
100	            throw rc.error("qr_error_correct_error");
101	        }
102	 
103	    }
104	 
105	 
106	    private static QRCode getQRCode(String text, int typeNumber,
107	            int errorCorrectLevel) throws IllegalArgumentException {
108	        if (typeNumber == 0) {
109	            return QRCode.getMinimumQRCode(text, errorCorrectLevel);
110	        } else {
111	            QRCode qr = new QRCode();
112	            qr.setTypeNumber(typeNumber);
113	            qr.setErrorCorrectLevel(errorCorrectLevel);
114	            qr.addData(text);
115	            qr.make();
116	            return qr;
117	        }
118	    }
119	 
120	    private static GIFImage createGIFImage(QRCode qrcode, int cellSize,
121	            int margin) throws IOException {
122	 
123	        int imageSize = qrcode.getModuleCount() * cellSize + margin * 2;
124	 
125	        GIFImage image = new GIFImage(imageSize, imageSize);
126	 
127	        for (int y = 0; y < imageSize; y++) {
128	 
129	            for (int x = 0; x < imageSize; x++) {
130	 
131	                if (margin <= x && x < imageSize - margin && margin <= y
132	                        && y < imageSize - margin) {
133	 
134	                    int col = (x - margin) / cellSize;
135	                    int row = (y - margin) / cellSize;
136	 
137	                    if (qrcode.isDark(row, col)) {
138	                        image.setPixel(x, y, 0);
139	                    } else {
140	                        image.setPixel(x, y, 1);
141	                    }
142	 
143	                } else {
144	                    image.setPixel(x, y, 1);
145	                }
146	            }
147	        }
148	 
149	        return image;
150	    }
3)前端页面:



<script type="text/javascript" src="/js/jquery/jquery.form-2.82.js"></script>
002	 
003	<script type="text/javascript">
004	 
005	    $(document).ready(function(){
006	 
007	                $("#submit").click(function(){
008	 
009	            var url = "/action/qrcode/generate?" + $("#qrcode_form").serialize();
010	 
011	            $(".QRCodeDiv img").attr("src",url+"&"+new Date().getTime());
012	 
013	            $("#gen_url").attr("href",url);
014	 
015	        });
016	 
017	                $("#zxing").popover({
018	 
019	            'title':'条形码处理类库 ZXing',
020	 
021	            'content':'ZXing是一个开源Java类库用于解析多种格式的1D/2D条形码。目标是能够对QR编码、Data Matrix、UPC的1D条形码进行解码。 其提供了多种平台下的客户端包括:J2ME、J2SE和Android。',
022	 
023	            'placement':'bottom'
024	 
025	        });
026	 
027	    });
028	 
029	</script>
030	 
031	<div id="mainContent" class="wrapper">
032	 
033	<div class="toolName">在线生成二维码(QR码)-采用<a id="zxing" href="http://www.oschina.net/p/zxing">ZXing</a>与<a href="http://www.d-project.com/">d-project</a><a data-toggle="modal" href="#advice" style="float:right;text-decoration:none;"><span class="badge badge-important"><i class="icon-envelope icon-white"></i> Feedback</span></a></div>
034	 
035	<div class="toolUsing clearfix">
036	 
037	    <div class="toolsTab  clearfix">
038	 
039	        <ul class="nav nav-tabs">
040	 
041	            <li class="active"><a href="/qr">转QR码</a></li>
042	 
043	            <li ><a href="/qr?type=2">二维码解码</a></li>
044	 
045	        </ul>
046	 
047	        <div class="clear"></div>
048	 
049	    </div>
050	 
051	    <form id="qrcode_form" method="post" >
052	 
053	            <div class="leftBar">
054	 
055	            <div class="title">URL或其他文本:</div>
056	 
057	            <textarea class="input-xlarge" name="data" onfocus="if(this.value=='http://osctools.net/qr'){this.value='';};this.select();" onblur="(this.value=='')?this.value='http://osctools.net/qr':this.value;">http://osctools.net/qr</textarea>
058	 
059	        </div>
060	 
061	        <div class="operateLR">
062	 
063	            <div class="OptDetail span1">
064	 
065	                <label>输出格式:</label>
066	 
067	                <select name="output" class="span1">
068	 
069	                    <option value="image/gif" selected>GIF</option>
070	 
071	                    <option value="image/jpeg">JPEG</option>
072	 
073	                    <option value="image/png">PNG</option>
074	 
075	                </select>
076	 
077	                <label>纠错级别:</label>
078	 
079	                <select name="error" class="span1">
080	 
081	                    <option value="L" selected>L 7%</option>
082	 
083	                    <option value="M">M 15%</option>
084	 
085	                    <option value="Q">Q 25%</option>
086	 
087	                    <option value="H">H 30%</option>
088	 
089	                </select>
090	 
091	                <label>类型:</label>
092	 
093	                <select name="type" class="span1">
094	 
095	                    <option value="0">自动</option>
096	 
097	                                        <option value="1">1</option>
098	 
099	                                        <option value="2">2</option>
100	 
101	                                        <option value="3">3</option>
102	 
103	                                        <option value="4">4</option>
104	 
105	                                        <option value="5">5</option>
106	 
107	                                        <option value="6">6</option>
108	 
109	                                        <option value="7">7</option>
110	 
111	                                        <option value="8">8</option>
112	 
113	                                        <option value="9">9</option>
114	 
115	                                        <option value="10">10</option>
116	 
117	                                    </select>
118	 
119	                <label>边缘留白:</label>
120	 
121	                <select name="margin" class="span1">
122	 
123	                                        <option value="0">0</option>
124	 
125	                                        <option value="1">1</option>
126	 
127	                                        <option value="2">2</option>
128	 
129	                                        <option value="3">3</option>
130	 
131	                                        <option value="4">4</option>
132	 
133	                                        <option value="5">5</option>
134	 
135	                                        <option value="6">6</option>
136	 
137	                                        <option value="7">7</option>
138	 
139	                                        <option value="8">8</option>
140	 
141	                                        <option value="9">9</option>
142	 
143	                                        <option value="10">10</option>
144	 
145	                                        <option value="11">11</option>
146	 
147	                                        <option value="12">12</option>
148	 
149	                                        <option value="13">13</option>
150	 
151	                                        <option value="14">14</option>
152	 
153	                                        <option value="15">15</option>
154	 
155	                                        <option value="16">16</option>
156	 
157	                                        <option value="17">17</option>
158	 
159	                                        <option value="18">18</option>
160	 
161	                                        <option value="19">19</option>
162	 
163	                                        <option value="20">20</option>
164	 
165	                                        <option value="21">21</option>
166	 
167	                                        <option value="22">22</option>
168	 
169	                                        <option value="23">23</option>
170	 
171	                                        <option value="24">24</option>
172	 
173	                                        <option value="25">25</option>
174	 
175	                                        <option value="26">26</option>
176	 
177	                                        <option value="27">27</option>
178	 
179	                                        <option value="28">28</option>
180	 
181	                                        <option value="29">29</option>
182	 
183	                                        <option value="30">30</option>
184	 
185	                                        <option value="31">31</option>
186	 
187	                                        <option value="32">32</option>
188	 
189	                                    </select>
190	 
191	                <label>原胞大小:</label>
192	 
193	                <select name="size" class="span1">
194	 
195	                                        <option value="1"  >1</option>
196	 
197	                                        <option value="2"  >2</option>
198	 
199	                                        <option value="3"  >3</option>
200	 
201	                                        <option value="4" selected >4</option>
202	 
203	                                    </select>
204	 
205	                <button class="btn btn-small btn-primary" id="submit" onclick="return false;">生成QR码</button>            </div>
206	 
207	        </div>
208	 
209	        <div class="rightBar">
210	 
211	                        <div class="title">QR码:</div>
212	 
213	            <div class="QRCodeDiv">
214	 
215	                <div class="QRWrapper">
216	 
217	                    <a id="gen_url" href="/action/qrcode/generate?size=4" target="_blank"><img src="/action/qrcode/generate?size=4"/></a>
218	 
219	                </div>
220	 
221	            </div>
222	 
223	        </div>
224	 
225	        </form>
226	 
227	</div>
228	 
229	</div>

4、使用ZXing解码QRcode

    1)下载Zxing-2.0.zip

    2)引入zxing-barcode_core.jar与zxing_barcode_j2se.jar到工程

    3)QRcodeAction代码:

@PostMethod
002	    @JSONOutputEnabled
003	    public void decode(RequestContext rc) throws IOException {
004	        //存在qrcode的网址
005	                String url = rc.param("url", "");
006	                //待解码的qrcdoe图像
007	                File img = rc.file("qrcode");
008	        if (StringUtils.isBlank(url) && img == null) {
009	            throw rc.error("qr_upload_or_url_null");
010	        }
011	 
012	        List<Result> results = new ArrayList<Result>();
013	        Config config = new Config();
014	        Inputs inputs = new Inputs();
015	 
016	        config.setHints(buildHints(config));
017	 
018	        if (StringUtils.isNotBlank(url)) {
019	            addArgumentToInputs(url, config, inputs);
020	        }
021	        if (img != null) {
022	            inputs.addInput(img.getCanonicalPath());
023	        }
024	        while (true) {
025	            String input = inputs.getNextInput();
026	            if (input == null) {
027	                break;
028	            }
029	            File inputFile = new File(input);
030	            if (inputFile.exists()) {
031	                try {
032	                    Result result = decode(inputFile.toURI(), config,rc);
033	                    results.add(result);
034	                } catch (IOException e) {
035	                }
036	            } else {
037	                try {
038	                    Result result = decode(new URI(input), config,rc);
039	                    results.add(result);
040	                } catch (Exception e) {
041	                }
042	            }
043	        }
044	        rc.print(new Gson().toJson(results));
045	    }
046	 
047	    private Result decode(URI uri,Config config,RequestContext rc)
048	            throws IOException {
049	        Map<DecodeHintType, ?> hints = config.getHints();
050	        BufferedImage image;
051	        try {
052	            image = ImageIO.read(uri.toURL());
053	        } catch (IllegalArgumentException iae) {
054	            throw rc.error("qr_resource_not_found");
055	        }
056	        if (image == null) {
057	            throw rc.error("qr_could_not_load_image");
058	        }
059	        try {
060	            LuminanceSource source = new BufferedImageLuminanceSource(image);
061	            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
062	            Result result = new MultiFormatReader().decode(bitmap, hints);
063	            return result;
064	        } catch (NotFoundException nfe) {
065	            throw rc.error("qr_no_barcode_found");
066	        }
067	    }
068	 
069	    private static Map<DecodeHintType, ?> buildHints(Config config) {
070	        Map<DecodeHintType, Object> hints = new EnumMap<DecodeHintType, Object>(
071	                DecodeHintType.class);
072	        Collection<BarcodeFormat> vector = new ArrayList<BarcodeFormat>(8);
073	        vector.add(BarcodeFormat.UPC_A);
074	        vector.add(BarcodeFormat.UPC_E);
075	        vector.add(BarcodeFormat.EAN_13);
076	        vector.add(BarcodeFormat.EAN_8);
077	        vector.add(BarcodeFormat.RSS_14);
078	        vector.add(BarcodeFormat.RSS_EXPANDED);
079	        if (!config.isProductsOnly()) {
080	            vector.add(BarcodeFormat.CODE_39);
081	            vector.add(BarcodeFormat.CODE_93);
082	            vector.add(BarcodeFormat.CODE_128);
083	            vector.add(BarcodeFormat.ITF);
084	            vector.add(BarcodeFormat.QR_CODE);
085	            vector.add(BarcodeFormat.DATA_MATRIX);
086	            vector.add(BarcodeFormat.AZTEC);
087	            vector.add(BarcodeFormat.PDF_417);
088	            vector.add(BarcodeFormat.CODABAR);
089	            vector.add(BarcodeFormat.MAXICODE);
090	        }
091	        hints.put(DecodeHintType.POSSIBLE_FORMATS, vector);
092	        if (config.isTryHarder()) {
093	            hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
094	        }
095	        if (config.isPureBarcode()) {
096	            hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
097	        }
098	        return hints;
099	    }
100	 
101	    private static void addArgumentToInputs(String argument, Config config,
102	            Inputs inputs) throws IOException {
103	        File inputFile = new File(argument);
104	        if (inputFile.exists()) {
105	            inputs.addInput(inputFile.getCanonicalPath());
106	        } else {
107	            inputs.addInput(argument);
108	        }
109	    }

4)前端页面:

<script type="text/javascript" src="/js/jquery/jquery.form-2.82.js"></script>
002	 
003	<script type="text/javascript">
004	 
005	    $(document).ready(function(){
006	 
007	                $("#qrcode_form").ajaxForm({
008	 
009	            success:function(json){
010	 
011	                if(json==null)
012	 
013	                    return;
014	 
015	                json = eval("("+json+")");
016	 
017	                if(json.msg){
018	 
019	                    alert(json.msg);
020	 
021	                    return;
022	 
023	                }
024	 
025	                if(json[0])
026	 
027	                    $("#result").val(json[0].text);
028	 
029	                else
030	 
031	                    $("#result").val("解码失败");
032	 
033	            }
034	 
035	        });
036	 
037	                $("#zxing").popover({
038	 
039	            'title':'条形码处理类库 ZXing',
040	 
041	            'content':'ZXing是一个开源Java类库用于解析多种格式的1D/2D条形码。目标是能够对QR编码、Data Matrix、UPC的1D条形码进行解码。 其提供了多种平台下的客户端包括:J2ME、J2SE和Android。',
042	 
043	            'placement':'bottom'
044	 
045	        });
046	 
047	    });
048	 
049	</script>
050	 
051	<div id="mainContent" class="wrapper">
052	 
053	<div class="toolName">在线生成二维码(QR码)-采用<a id="zxing" href="http://www.oschina.net/p/zxing">ZXing</a>与<a href="http://www.d-project.com/">d-project</a><a data-toggle="modal" href="#advice" style="float:right;text-decoration:none;"><span class="badge badge-important"><i class="icon-envelope icon-white"></i> Feedback</span></a></div>
054	 
055	<div class="toolUsing clearfix">
056	 
057	    <div class="toolsTab  clearfix">
058	 
059	        <ul class="nav nav-tabs">
060	 
061	            <li ><a href="/qr">转QR码</a></li>
062	 
063	            <li class="active"><a href="/qr?type=2">二维码解码</a></li>
064	 
065	        </ul>
066	 
067	        <div class="clear"></div>
068	 
069	    </div>
070	 
071	    <form id="qrcode_form" method="post" action="/action/qrcode/decode">
072	 
073	            <div class="topBar">
074	 
075	            <div class="title">
076	 
077	                <label class="radio" for="upload_url">图片URL:
078	 
079	                    <input checked="checked" name="upload_ctn" id="upload_url" style="margin-right:5px;" type="radio" onchange="if(this.checked){$('input[name=\'url\']').removeAttr('disabled');$('input[name=\'qrcode\']').attr('disabled','disabled')}"/>
080	 
081	                </label>
082	 
083	            </div>
084	 
085	            <input name="url" id="url" style="width:100%;height:40px;margin:0 0 10px 0;" onfocus="if(this.value=='http://www.osctools.net/img/qr.gif'){this.value='';};this.select();" onblur="(this.value=='')?this.value='http://www.osctools.net/img/qr.gif':this.value;" value="http://www.osctools.net/img/qr.gif"/>
086	 
087	            <div class="title">
088	 
089	                <label  class="radio" for="upload_img">上传图片:
090	 
091	                    <input style="margin-right:5px;" name="upload_ctn" id="upload_img" type="radio" onchange="if(this.checked){$('input[name=\'qrcode\']').removeAttr('disabled');$('input[name=\'url\']').attr('disabled','disabled')}"/>
092	 
093	                </label>
094	 
095	            </div>
096	 
097	            <input disabled="disabled" name="qrcode" type="file" class="input-file"/>
098	 
099	            <input class="btn btn-primary" value="解码" type="submit"/>
100	 
101	        </div>
102	 
103	        <div class="bottomBar">
104	 
105	            <div class="title">解码结果:</div>
106	 
107	            <textarea id="result"></textarea>
108	 
109	        </div>
110	 
111	        </form>
112	 
113	</div>
114	</div>
注意:其中牵涉到的 RequestContext类见此处: http://www.oschina.net/code/snippet_12_2


转载于:https://my.oschina.net/mkh/blog/150683

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值