二维码打印

1.      二维码简介

二维码(2-dimensional bar code),又称二维条码,它是用特定的几何图形按一定规律在平面(二维方向)上分布的黑白相间的图形,是所有信息数据的一把钥匙。在现代商业活动中,可实现的应用十分广泛,如:产品防伪/溯源、广告推送、网站链接、数据下载、商品交易、定位/导航、电子凭证、车辆管理等等。根据编码规则的不同,二维码主要有Data Matrix,MaxiCode, Aztec,QR Code, Vericode,PDF417,Ultracode, Code 49, Code 16K, Han Xin Code 等,现在使用最多的的是QR Code。



2.QR CODE码

QR Code码是由日本Denso公司于1994年9月研制的一种矩阵二维码符号,目的是用来追踪汽车零部件(从QRCode的诞生原因可以看出它跟ERP颇有渊源)。

2.1QRCode优点

快速:

在用CCD识读QR Code码时,整个QR Code码符号中信息的读取是通过QR Code码符号的位置探测图形,用硬件来实现,因此,信息识读过程所需时间很短,它具有超高速识读特点。

全方位:

QR Code码具有全方位(360°)识读特点,这是QR Code码优于行排式二维条码如四一七条码的另一主要特点,由于四一七条码是将一维条码符号在行排高度上的截短来实现的,因此,它很难实现全方位识读,其识读方位角仅为±10°。

信息容量大:

QRCode最大的数据容量是(冗余级别为L时):

数字数据:7,089个字符

字母数据: 4,296个字符

8位字节数据: 2,953个字符

中国/日本汉字数据:1,817个字符

容错率高:

根据不同的冗余级别,QRCode具有一定的容错率,二维码被污损的面积在一定的范围内时还可以被读取出来,二维码有4种冗余级别,分别具有不同的纠错能力:

L级:约可纠错7%的数据码字

M级:约可纠错15%的数据码字

Q级:约可纠错25%的数据码字

        H级:约可纠错30%的数据码字

2.2QRCode原理

QRCode原理就是把信息以01编码打出来,深色模块表示二进制"1",浅色模块表示二进制"0",以下是QRCode的具体的编码信息分布图

     

      

    

位置探测图形、位置探测图形分隔符:

用于对二维码的定位,对每个QR码来说,位置都是固定存在的,只是大小规格会有所差异;这些黑白间隔的矩形块很容易进行图像处理的检测。

校正图形:

根据尺寸的不同,矫正图形的个数也不同。矫正图形主要用于QR码形状的矫正,尤其是当QR码印刷在不平坦的面上,或者拍照时候发生畸变等。

定位图形:

这些小的黑白相间的格子就好像坐标轴,在二维码上定义了网格。

格式信息

表示该二维码的纠错级别,分为L、M、Q、H;

数据区域:

使用黑白的二进制网格编码内容。8个格子可以编码一个字节。

版本信息:

即二维码的规格,QR码符号共有40种规格的矩阵(一般为黑白色),从21x21(版本1),到177x177(版本40),每一版本符号比前一版本 每边增加4个模块。

纠错码字:

用于修正二维码损坏带来的错误。

 

2.3简要编码过程

1、   数据分析:确定编码的字符类型,按相应的字符集转换成符号字符; 选择纠错等级,在规格一定的条件下,纠错等级越高其真实数据的容量越小。

2、   数据编码:将数据字符转换为位流,每8位一个码字,整体构成一个数据的码字序列。其实知道这个数据码字序列就知道了二维码的数据内容。

3、   纠错编码:按需要将上面的码字序列分块,并根据纠错等级和分块的码字,产生纠错码字,并把纠错码字加入到数据码字序列后面,成为一个新的序列。

在二维码规格和纠错等级确定的情况下,其实它所能容纳的码字总数和纠错码字数也就确定了,比如:版本10,纠错等级时H时,总共能容纳346个码字,其中224个纠错码字。 就是说二维码区域中大约1/3的码字时冗余的。对于这224个纠错码字,它能够纠正112个替代错误(如黑白颠倒)或者224个拒读错误(无法读到或者无法译码), 这样纠错容量为:112/346=32.4% 

4、   构造最终数据信息:在规格确定的条件下,将上面产生的序列按次序放入分块中 按规定把数据分块,然后对每一块进行计算,得出相应的纠错码字区块,把纠错码字区块 按顺序构成一个序列,添加到原先的数据码字序列后面。 如:D1, D12, D23, D35, D2, D13, D24, D36, ... D11, D22, D33, D45, D34, D46, E1, E23,E45, E67, E2, E24, E46, E68,...

5、   构造矩阵:将探测图形、分隔符、定位图形、校正图形和码字模块放入矩阵中。

把上面的完整序列填充到相应规格的二维码矩阵的区域中

6、   掩摸:将掩摸图形用于符号的编码区域,使得二维码图形中的深色和浅色(黑色和白色)区域能够比率最优的分布。

3.框架安装

1、上传qrcode1.5.jar至数据库服务器/home/oraprod/(路径随意)

2、telnet用oracle用户登录数据库服务器(oraprod)

3、进入qrcode1.5.jar所在目录:cd /home/oraprod

4、执行以下命令:loadjava -u apps/cpnds2014apps@PROD  -r -v –f qrcode1.5.jar

 

 

4.二维码开发

4.1JSP

         可直接编译一下代码,作用主要是调用encode2方法,通过jsp将要显示的二维码内容contents转换成矩阵二维码符号,即qrcode码。 

 1 create or replace and compile java source named APPS.cux_qrcode as
 2 import java.awt.image.BufferedImage;  
 3 import java.io.File;  
 4 import java.io.IOException;  
 5 import java.util.Hashtable;  
 6 import javax.imageio.ImageIO;  
 7 import com.google.zxing.BarcodeFormat;  
 8 import com.google.zxing.BinaryBitmap;  
 9 import com.google.zxing.DecodeHintType;  
10 import com.google.zxing.LuminanceSource;  
11 import com.google.zxing.MultiFormatReader;  
12 import com.google.zxing.MultiFormatWriter;  
13 import com.google.zxing.CuxMultiFormatWriter;  
14 import com.google.zxing.Reader;  
15 import com.google.zxing.ReaderException;  
16 import com.google.zxing.Result;  
17 import com.google.zxing.client.j2se.BufferedImageLuminanceSource;  
18 import com.google.zxing.client.j2se.MatrixToImageWriter;
19 import com.google.zxing.common.ByteMatrix;  
20 import com.google.zxing.common.HybridBinarizer; 
21 import oracle.sql.* ;
22 import java.sql.*;
23 import java.io.OutputStream; 
24 
25 public class QRCode
26 {
27 
28 public static String encode(String content,String path,int width,int height)
29   {
30    try {  
31             ByteMatrix byteMatrix; 
32             byteMatrix= new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height); 
33             File file = new File(path); 
34             MatrixToImageWriter.writeToFile(byteMatrix, "png", file);  
35             return "S";
36         } catch (Exception e) {  
37             e.printStackTrace();  
38             return "-1@"+e.toString();
39         }  
40   }
41 
42   public static BLOB encode2(String contents,int width, int height,int padding, String imageFormat) {
43 
44         try {  
45         
46             ByteMatrix byteMatrix;  
47             byteMatrix= new CuxMultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, padding);
48            
49             Connection conn = DriverManager.getConnection(
50                     "jdbc:default:connection:") ;     
51             BLOB outBlob = BLOB.createTemporary( conn, true , BLOB.DURATION_CALL) ;
52             MatrixToImageWriter.writeToStream(byteMatrix, imageFormat, outBlob.getBinaryOutputStream());
53             
54             outBlob.getBinaryOutputStream().close();
55             return outBlob ;
56             
57         } catch (Exception e) {  
58             e.printStackTrace();  
59             System.out.println(e.toString()); 
60         }
61     return null;  
62     }     
63     
64   public static String decode(String imgPath){
65    try {    
66         Reader reader = new MultiFormatReader();    
67         File file = new File(imgPath);  
68         BufferedImage image;  
69         try {  
70             image = ImageIO.read(file);  
71             if (image == null) {  
72                 System.out.println("Could not decode image");  
73                 return "-1@Could not decode image";
74             }  
75             LuminanceSource source = new BufferedImageLuminanceSource(image);  
76             BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(  
77                     source));  
78             Result result;  
79             Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();   
80            
81             result = new MultiFormatReader().decode(bitmap, hints);  
82             String resultStr = result.getText();  
83             return resultStr;
84   
85         } catch (IOException ioe) {  
86             return "-1@" + ioe.toString();  
87         } catch (ReaderException re) {  
88             return "-1@" + re.toString();  
89         }  
90   
91     } catch (Exception ex) {  
92         ex.printStackTrace();  
93         return "-1@" + ex.toString();
94     }  
95  }
96 }
97 /
代码

 

4.2调用JSP方法,获取二维码

     可直接编译一下代码,无需更改。主要是获取到qrcode码到一个BLOB对象。并通过blob_to_clob方法,将BLOB转化成CLOB。

所用到的主要代码:

  1 --包头
  2 CREATE OR REPLACE PACKAGE cux_qrcode_util_pkg AS
  3 
  4   g_qrcode_file_path  VARCHAR2(400) := '/cfd/';
  5   g_return_error_code VARCHAR2(3) := '-1@';
  6 
  7   PROCEDURE decode(p_image_path IN VARCHAR2,
  8                    x_content    OUT VARCHAR2,
  9                    x_status     OUT VARCHAR2,
 10                    x_message    OUT VARCHAR2);
 11 
 12   PROCEDURE encode(p_contents       IN VARCHAR2,
 13                    p_file_name      IN VARCHAR2,
 14                    p_width          IN NUMBER,
 15                    p_height         IN NUMBER,
 16                    x_full_file_name OUT VARCHAR2,
 17                    x_status         OUT VARCHAR2,
 18                    x_message        OUT VARCHAR2);
 19 
 20   FUNCTION encode2(p_contents    IN VARCHAR2,
 21                    p_width       IN NUMBER,
 22                    p_height      IN NUMBER,
 23                    p_padding     IN NUMBER,
 24                    p_imageformat IN VARCHAR2) RETURN BLOB AS
 25   
 26     LANGUAGE JAVA NAME 'QRCode.encode2(java.lang.String,int,int,int,java.lang.String) return oracle.sql.BLOB';
 27 
 28   FUNCTION blob_to_clob(p_blob BLOB) RETURN CLOB;
 29 
 30 END cux_qrcode_util_pkg;
 31 --包体
 32 CREATE OR REPLACE PACKAGE BODY cux_qrcode_util_pkg AS
 33 
 34   g_debug       VARCHAR2(1) := nvl(fnd_profile.value('AFLOG_ENABLED'), 'N');
 35   g_request_id  NUMBER := fnd_global.conc_request_id;
 36   g_success     VARCHAR(1) := 'S';
 37   g_warning     VARCHAR2(1) := 'W';
 38   g_error       VARCHAR2(1) := 'E';
 39   g_date_format VARCHAR2(30) := 'YYYYMMDDHH24MISS';
 40 
 41   FUNCTION encode(contents IN VARCHAR2,
 42                   filename IN VARCHAR2,
 43                   width    IN NUMBER,
 44                   height   IN NUMBER) RETURN VARCHAR2 AS
 45     LANGUAGE JAVA NAME 'QRCode.encode(java.lang.String,java.lang.String,int,int) return java.lang.String';
 46 
 47   FUNCTION decode(imgpath IN VARCHAR2) RETURN VARCHAR2 AS
 48     LANGUAGE JAVA NAME 'QRCode.decode(java.lang.String) return java.lang.String';
 49 
 50   
 51   PROCEDURE encode(p_contents       IN VARCHAR2,
 52                    p_file_name      IN VARCHAR2,
 53                    p_width          IN NUMBER,
 54                    p_height         IN NUMBER,
 55                    x_full_file_name OUT VARCHAR2,
 56                    x_status         OUT VARCHAR2,
 57                    x_message        OUT VARCHAR2) IS
 58     l_status         VARCHAR2(1);
 59     l_message        VARCHAR2(4000);
 60     l_full_file_name VARCHAR2(1000);
 61     l_sysdate        VARCHAR2(20) := to_char(SYSDATE, g_date_format);
 62   BEGIN
 63     x_status  := g_success;
 64     x_message := NULL;
 65   
 66     l_full_file_name := g_qrcode_file_path || p_file_name || l_sysdate ||
 67                         '.png';
 68     dbms_output.put_line('file_path: ' || l_full_file_name);
 69     l_message := substr(encode(p_contents,
 70                                l_full_file_name,
 71                                p_width,
 72                                p_height),
 73                         0,
 74                         4000);
 75   
 76     IF l_message = g_success THEN
 77       l_status  := g_success;
 78       l_message := NULL;
 79     ELSE
 80       l_status := g_error;
 81     END IF;
 82   
 83     x_status         := l_status;
 84     x_message        := l_message;
 85     x_full_file_name := l_full_file_name;
 86   EXCEPTION
 87     WHEN fnd_api.g_exc_unexpected_error THEN
 88       x_status  := g_error;
 89       x_message := 'encode Program Unexpected error.' || SQLERRM;
 90     WHEN fnd_api.g_exc_error THEN
 91       x_status  := g_warning;
 92       x_message := 'encode Program error.' || SQLERRM;
 93   END encode;
 94 
 95   PROCEDURE decode(p_image_path IN VARCHAR2,
 96                    x_content    OUT VARCHAR2,
 97                    x_status     OUT VARCHAR2,
 98                    x_message    OUT VARCHAR2) IS
 99     l_status  VARCHAR2(1);
100     l_message VARCHAR2(4000);
101     l_content VARCHAR2(32767);
102   BEGIN
103     x_status  := g_success;
104     x_message := NULL;
105   
106     l_content := decode(p_image_path);
107   
108     IF instr(l_content, g_return_error_code) = 1 THEN
109       l_status  := g_error;
110       l_message := substr(l_content, length(g_return_error_code) + 1, 4000);
111       l_content := NULL;
112     ELSE
113       l_status := g_success;
114     END IF;
115   
116     x_content := l_content;
117     x_status  := l_status;
118     x_message := l_message;
119   EXCEPTION
120     WHEN fnd_api.g_exc_unexpected_error THEN
121       x_status  := g_error;
122       x_message := 'decode Program Unexpected error.' || SQLERRM;
123     WHEN fnd_api.g_exc_error THEN
124       x_status  := g_warning;
125       x_message := 'decode Program error.' || SQLERRM;
126     
127   END decode;
128 
129   FUNCTION blob_to_clob(p_blob BLOB) RETURN CLOB IS
130     l_result CLOB;
131   BEGIN
132     dbms_lob.createtemporary(lob_loc => l_result, cache => FALSE, dur => 0);
133     wf_mail_util.encodeblob(p_blob, l_result);
134     RETURN(l_result);
135   END blob_to_clob;
136 
137 END cux_qrcode_util_pkg;
代码

 

4.3定义报表,RTF模板。XML

 

报表示例,代码如下:

 1 CREATE OR REPLACE PACKAGE cux_fa_dual_pkg IS
 2   /*
 3     description:二维码打印测试
 4     TIME:2015/08/10     wang.chen
 5   */
 6   PROCEDURE main(errbuf OUT VARCHAR2, retcode OUT VARCHAR2);
 7 
 8 END cux_fa_dual_pkg;
 9 
10 CREATE OR REPLACE PACKAGE BODY cux_fa_dual_pkg IS
11 
12   PROCEDURE output(p_text IN VARCHAR2) IS
13   BEGIN
14     fnd_file.put_line(fnd_file.output, p_text);
15     dbms_output.put_line(p_text);
16   END output;
17 
18 
19   PROCEDURE process_request(x_return_status OUT VARCHAR2, x_return_msg OUT VARCHAR) IS
20   
21     CURSOR cur_dual IS
22       SELECT 'www.hand-china.com' company,
23              '启用时间: ' || substr(to_char(SYSDATE, 'YYYY-MM'), 1, 4) || '' ||
24              substr(to_char(SYSDATE, 'YYYY-MM'), 6, 2) || '' start_date
25         FROM dual
26        WHERE 1 = 1;
27   
28     l_encoding_data VARCHAR2(32767);
29     l_blob          BLOB;
30     l_clob          CLOB;
31     l_width         NUMBER := 0;
32   
33   BEGIN
34   
35     -- l_width := 100;
36     output('<?xml version="1.0" encoding="UTF-8"?>');
37     output('<DUALS>');
38   
39     FOR rec_dual IN cur_dual LOOP
40       --l_encoding_data := NULL;
41       l_encoding_data := l_encoding_data || rec_dual.company || chr(10) || chr(13);
42     
43       l_encoding_data := l_encoding_data || rec_dual.start_date;
44       -- Dbms_Output.put_line(l_encoding_data);
45       IF length(l_encoding_data) > 32 THEN
46         l_width := 114;
47       ELSIF length(l_encoding_data) < 25 THEN
48         l_width := 100;
49       ELSE
50         l_width := 110;
51       END IF;
52     
53       l_clob := NULL;
54       l_blob := cux_qrcode_util_pkg.encode2(p_contents    => l_encoding_data,
55                                             p_width       => l_width,
56                                             p_height      => l_width,
57                                             p_padding     => 0,
58                                             p_imageformat => 'png');
59       l_clob := cux_qrcode_util_pkg.blob_to_clob(l_blob);
60     
61       output('<DUAL>');
62       output('<COMPANY>' || rec_dual.company || '</COMPANY>');
63       output('<START_DATE>' || rec_dual.start_date || '</START_DATE>');
64       output('<QRCODE>' || l_clob || '</QRCODE>');
65       --INSERT INTO cux_test_clob (clob_txt) VALUES (l_clob);
66       output('</DUAL>');
67     
68     END LOOP;
69   
70     output('</DUALS>');
71   
72   EXCEPTION
73     WHEN OTHERS THEN
74       x_return_status := fnd_api.g_ret_sts_error;
75       x_return_msg    := substr(SQLERRM, 1, 1000);
76   END process_request;
77 
78   PROCEDURE main(errbuf OUT VARCHAR2, retcode OUT VARCHAR2) IS
79     l_return_status VARCHAR2(1) := fnd_api.g_ret_sts_success;
80     l_return_msg    VARCHAR2(4000) := '';
81   BEGIN
82     errbuf  := '';
83     retcode := 0;
84   
85     process_request(x_return_status => l_return_status, x_return_msg => l_return_msg);
86   
87   EXCEPTION
88     WHEN fnd_api.g_exc_error THEN
89       retcode := 1;
90       errbuf  := REPLACE(l_return_msg, chr(0), ' ');
91     WHEN fnd_api.g_exc_unexpected_error THEN
92       retcode := 2;
93       errbuf  := REPLACE(l_return_msg, chr(0), ' ');
94     WHEN OTHERS THEN
95       retcode := 2;
96       errbuf  := SQLERRM;
97   END main;
98 
99 END cux_fa_dual_pkg;
代码

 

获取定义RTF模板时需加载的XML:

 1 <?xml version="1.0" encoding="GBK"?>
 2 <DUALS>
 3 <DUAL>
 4 <COMPANY>www.hand-china.com</COMPANY>
 5 <START_DATE>启用时间: 2015年08月</START_DATE>
 6 <QRCODE>iVBORw0KGgoAAAANSUhEUgAAAHIAAAByCAYAAACP3YV9AAADA0lEQVR42u2dQW7k
 7 MAwE/f9P794DBLHIalkUqoEcBshkbJXBkC1S8/xTV+hxCQSpBKkEqQQpSCVIJUgl
 8 SEEqQSpBKkEqQQpSXQjyeZ7Sz8/3//b6t8/76zr+uj76/qj1EKQgGZDV368uyNsF
 9 f/sA0NedWj9BCrJ3g29D6WqoeRuCq2Cr4LrrIUhBfguyGuJWk45T/nUIUpCzQFYB
10 VRcodX2CFORd5Qd9o29DNWVAWEcK8k6LbuprvVZBfgNyV7K0qwzoGgefraMgBYlY
11 Y1VznC4j0lZc15IUpCB76XsVTHdbi7bsuuVS2ggQpCBrBfOukEaHYMryG9vqIchh
12 IGnrqhrKUoU51WJyfGgV5CUg6XKj+wBU2ym7yU/XiBCkINnQWr3QapnQNQyoB4P+
13 XEEKco/pnU6GKAuMGilYLccEKchM+dFdoK55TpUNdBIVb1kRpCBbyUzVDKeTr9To
14 QfdBFaQgM+VHuvBOjQqkzXFBCnJvaKU3hruhMDVsdEqzliAFWQsp1dCYLrRpM3t8
15 85Ugh4OshhZqG6hbBtGbAKmySpCC7BXeVHKSLn9WP59uHhOkILOhlW796JrkdHJW
16 NSzGmOaCHApytWBPGw1UWbB6P1+P5QlSkGsLnjabq0CpVpRukiVIQe6x6Og0nLa4
17 0gcgbdtWE6QgkRvtlgWroZIeQaCsO0EKMmvRUaY73QCcGljt/j1BCvKM8qO7wFTI
18 pg6hSCdnghQka03Rlhy90ZwyCsYmO4IcCpK24KhkIfUFLV+NQghSkNk0PZ1M7Bqo
19 pd8vSEHuDa3V8oE28amDlnaHUkEKMrT9Apna6Y1dqt3z2NAqyEtA7v56BCpE0yPz
20 q8nVmEMFBTkUZMpk71pqVaBU8jK201yQl4CkmrDopq7UEdVUWSJIQZ4Nkgq53W0l
21 usy5totOkJfOR1LJUup4T2q0/trQKshLyo+qFZcajKWP/RyX7AhyOEj6i1JoEHSD
22 MQVckIJkQaozJEhBKkEqQSpBClIJUglSCVKQSpBKkEqQSpCCVAfqPyGDaYroYl8y
23 AAAAAElFTkSuQmCC</QRCODE>
24 </DUAL>
25 </DUALS>
XML

 

通过TEST  main,得到输出的xml

---解析出来的encoding为UTF-8,在定义rtf模板加载xml时,需改为GBK,否则会报错

--通过output(p_text IN VARCHAR2)输出得到的XML,可能存在的一种情况:当需要输出的二维码数据太长,超过VARCHAR2的最大长度时,QRCODE将获取不到全部内容,内容被截断,导致最后会得不到二维码png,可使用lob对象来获取输出。

 

RTF模板:

 

QRCODE:<fo:instream-foreign-object content-type="image/png"><xsl:value-of  select="QRCODE"/></fo:instream-foreign-object>

作用:固定形式,无需更改,大概是将QRCODE输出类型设置成图片png

 

在EBS系统中上传RTF模板

Xml Publish Administrator 责任à主页à 数据定义

创建数据定义

 

创建模板

 

 

 

4.4跑请求,打印二维码

                (定义请求略)

                 结果:

           

 

 

转载于:https://www.cnblogs.com/wang-chen/p/5756671.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值