去网上找了很多关于QR码创建的代码,结果都没有很满意的解释,于是就拿了一段网上出现概率比较高的代码进行分析。有什么不好的地方请及时指正!
public class QRCodeEncoder {
/**
* 编码字符串内容到目标new File(test.png)中
* @param encodeddata
* @param destFile
* @throws IOException
*/
//字符串->用gbk编码将字符串表示出来存到byte[]数组中->用Qrcode中的calQrcode(d)将转换后的编码变为boolean形式->根据boolean数组值在图片中画出二维码
public static void qrCodeEncode(String encodeddata,File destFile) throws IOException{
Qrcode qrcode = new Qrcode();
//错误修正容量
//L水平 7%的字码可被修正
//M水平 15%的字码可被修正
//Q水平 25%的字码可被修正
//H水平 30%的字码可被修正
//QR码有容错能力,QR码图形如果有破损,仍然可以被机器读取内容,最高可以到7%~30%面积破损仍可被读取。
//相对而言,容错率愈高,QR码图形面积愈大。所以一般折衷使用15%容错能力。
qrcode.setQrcodeErrorCorrect('M');//设置错误修正容量
qrcode.setQrcodeEncodeMode('B');//设置编码方式
qrcode.setQrcodeVersion(7);//设置版本号
byte[] d = encodeddata.getBytes("utf-8");//得到指定编码的字节数组 字符串--->字节数组 ,得到的是字符编码.注意这儿用utf-8,不要用其他的,否则用微信扫出来是乱码。
BufferedImage bi = new BufferedImage(139, 139,BufferedImage.TYPE_INT_RGB);//新建一个宽为139,高为139,图片类型为BufferedImage.TYPE_INT_RGB的BufferedImage
// createGraphics
Graphics2D g = bi.createGraphics();
// set background
g.setBackground(Color.WHITE);
g.clearRect(0, 0, 139, 139);
//设置二维码图片颜色
g.setColor(Color.BLACK);
//将数据转换为boolean值,若为true,则在相应的位置填充
if (d.length > 0 && d.length < 123) {
boolean[][] b = qrcode.calQrcode(d);//快速响应QR码,将byte[]数组转换为bollean[][],便于后期二维码图片实现
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b.length; j++) {
//System.out.print(b[j][i]+"~");
if (b[j][i]) {
g.fillRect(j * 3 + 2, i * 3 + 2, 3, 3);
}
}
}
}
g.dispose();
bi.flush();
ImageIO.write(bi, "png", destFile);//图片存入对应位置,注意,destFile是产生的图片名称
System.out.println("Input Encoded data is:"+encodeddata);
}
public static void main(String[] args) throws IOException {
QRCodeEncoder q = new QRCodeEncoder();
q.qrCodeEncode("宝宝第一次写博客啦", new File("test.png"));
}
}
宝宝将对以上的一些代码进行分析
1.byte[] d = encodeddata.getBytes("utf-8");
对这儿不是很清楚的,可以参考String(byte[] bytes, Charset charset) 和 getBytes() 使用;
2.BufferedImage bi = new BufferedImage(139, 139, BufferedImage.TYPE_INT_RGB);
这儿请看源码
/**
* Constructs a <code>BufferedImage</code> of one of the predefined
* image types. The <code>ColorSpace</code> for the image is the
* default sRGB space.
* @param width width of the created image
* @param height height of the created image
* @param imageType type of the created image
* @see ColorSpace
* @see #TYPE_INT_RGB
* @see #TYPE_INT_ARGB
* @see #TYPE_INT_ARGB_PRE
* @see #TYPE_INT_BGR
* @see #TYPE_3BYTE_BGR
* @see #TYPE_4BYTE_ABGR
* @see #TYPE_4BYTE_ABGR_PRE
* @see #TYPE_BYTE_GRAY
* @see #TYPE_USHORT_GRAY
* @see #TYPE_BYTE_BINARY
* @see #TYPE_BYTE_INDEXED
* @see #TYPE_USHORT_565_RGB
* @see #TYPE_USHORT_555_RGB
*/
public BufferedImage(int width,
int height,
int imageType) {
switch (imageType) {
case TYPE_INT_RGB:
{
colorModel = new DirectColorModel(24, 0x00ff0000, // Red 0x0000ff00, // Green 0x000000ff, // Blue 0x0 // Alpha );
raster = colorModel.createCompatibleWritableRaster(width, height);
}
break;
case TYPE_INT_ARGB:
{
colorModel = ColorModel.getRGBdefault();
raster = colorModel.createCompatibleWritableRaster(width, height);
}
break;
case TYPE_INT_ARGB_PRE:
{
colorModel = new
DirectColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB),
32,
0x00ff0000,// Red
0x0000ff00,// Green
0x000000ff,// Blue
0xff000000,// Alpha
true, // Alpha Premultiplied
DataBuffer.TYPE_INT
);
raster = colorModel.createCompatibleWritableRaster(width,
height);
}
break;
case TYPE_INT_BGR:
{
colorModel = new DirectColorModel(24,
0x000000ff, // Red
0x00ff0000 // Blue );
raster = colorModel.createCompatibleWritableRaster(width, height);
}
break;
case TYPE_3BYTE_BGR:
{
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
int[] nBits = {8, 8, 8};
int[] bOffs = {2, 1, 0};
colorModel = new ComponentColorModel(cs, nBits, false, false,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, width*3, 3, bOffs, null); }
break;
case TYPE_4BYTE_ABGR:
{ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
int[] nBits = {8, 8, 8, 8};
int[] bOffs = {3, 2, 1, 0};
colorModel = new ComponentColorModel(cs, nBits, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
width, height,
width*4, 4,
bOffs, null);
}
break;
case TYPE_4BYTE_ABGR_PRE:
{
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
int[] nBits = {8, 8, 8, 8};
int[] bOffs = {3, 2, 1, 0};
colorModel = new ComponentColorModel(cs, nBits, true, true,
Transparency.TRANSLUCENT,
DataBuffer.TYPE_BYTE);
raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
width, height,
width*4, 4,
bOffs, null);
}
break;
case TYPE_BYTE_GRAY:
{
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
int[] nBits = {8};
colorModel = new ComponentColorModel(cs, nBits, false, true,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
raster = colorModel.createCompatibleWritableRaster(width,
height);
}
break;
case TYPE_USHORT_GRAY:
{
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
int[] nBits = {16};
colorModel = new ComponentColorModel(cs, nBits, false, true,
Transparency.OPAQUE,
DataBuffer.TYPE_USHORT);
raster = colorModel.createCompatibleWritableRaster(width,
height);
}
break;
case TYPE_BYTE_BINARY:
{
byte[] arr = {(byte)0, (byte)0xff};
colorModel = new IndexColorModel(1, 2, arr, arr, arr);
raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
width, height, 1, 1, null);
}
break;
case TYPE_BYTE_INDEXED:
{
// Create a 6x6x6 color cube
int[] cmap = new int[256];
int i=0;
for (int r=0; r < 256; r += 51) {
for (int g=0; g < 256; g += 51) {
for (int b=0; b < 256; b += 51) {
cmap[i++] = (r<<16)|(g<<8)|b;
}
}
}
// And populate the rest of the cmap with gray values
int grayIncr = 256/(256-i);
// The gray ramp will be between 18 and 252
int gray = grayIncr*3;
for (; i < 256; i++) {
cmap[i] = (gray<<16)|(gray<<8)|gray;
gray += grayIncr;
}
colorModel = new IndexColorModel(8, 256, cmap, 0, false, -1,
DataBuffer.TYPE_BYTE);
raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
width, height, 1, null);
}
break;
case TYPE_USHORT_565_RGB:
{
colorModel = new DirectColorModel(16,
DCM_565_RED_MASK,
DCM_565_GRN_MASK,
DCM_565_BLU_MASK
);
raster = colorModel.createCompatibleWritableRaster(width,
height);
}
break;
case TYPE_USHORT_555_RGB:
{
colorModel = new DirectColorModel(15,
DCM_555_RED_MASK,
DCM_555_GRN_MASK,
DCM_555_BLU_MASK
);
raster = colorModel.createCompatibleWritableRaster(width,
height);
}
break;
default:
throw new IllegalArgumentException ("Unknown image type " +
imageType);
}
this.imageType = imageType;
}
3. if (d.length > 0 && d.length < 123) {
boolean[][] b = qrcode.calQrcode(d);//快速响应QR码,将byte[]数组转换为bollean[][],便于后期二维码图片实现
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b.length; j++) {
//System.out.print(b[j][i]+"~");
if (b[j][i]) {
g.fillRect(j * 3 + 2, i * 3 + 2, 3, 3);
}
}
}
}
这儿是在之前byte[] d = encodeddata.getBytes(“utf-8”)的基础上,将获取的byte[] d通过boolean[][] b = qrcode.calQrcode(d)转变为boolean,即所有的值变为true或者false。举个例子,原来有encodeddata=“a”,经过byte[] d = encodeddata.getBytes(“utf-8”)后,a转换成了“97”,再经过boolean[][] b = qrcode.calQrcode(d),则97又转换成了true和false组成的布尔数组。在这个基础上实现二维码图片。
即String->byte[]->boolean[][]->二维码图片。
最后附上本宝宝做好的二维码给大家。