博客地址:https://ainyi.com/58

Java 开发精美艺术二维码

看到网络上各种各样的二维码层出不穷,好像很炫酷的样子,一时兴起,我也要制作这种炫酷二维码效果

例如:

根据以往例子

根据之前所做的小项目 java 开发二维码系统

以这个为基础,将实现精美艺术二维码

基本代码:

// 创建二维码对象
Qrcode qrcode = new Qrcode();
// 设置二维码的纠错级别
// L(7%) M(15%) Q(25%) H(30%)
qrcode.setQrcodeErrorCorrect('L'); // 一般纠错级别小一点
// 设置二维码的编码模式 Binary(按照字节编码模式)
qrcode.setQrcodeEncodeMode('B');
// 设置二维码的版本号 1-40 1:20*21 2:25*25 40:177*177
qrcode.setQrcodeVersion(7);
// 生成二维码中要存储的信息
String qrData = "https://ainyi.com";
// 设置一下二维码的像素
int width = 300;
int height = 300;
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 绘图
Graphics2D gs = bufferedImage.createGraphics();
gs.setBackground(Color.WHITE);
gs.setColor(Color.BLACK);
gs.clearRect(0, 0, width, height); // 清除下画板内容 // 设置下偏移量,如果不加偏移量,有时会导致出错
int pixoff = 2; byte[] d = qrData.getBytes("utf-8");
if(d.length > 0 && d.length <120){
boolean[][] s = qrcode.calQrcode(d);
for(int i=0;i<s.length;i++){
for(int j=0;j<s.length;j++){
if(s[j][i]){
gs.fillRect(j*3+pixoff, i*3+pixoff, 3, 3);
}
}
}
}
gs.dispose();
bufferedImage.flush();
ImageIO.write(bufferedImage, "png", new File("E:/code/qrcode.png"));

准备工作

java 可以实现生成二维码,需要用到 Qrcode 的 jar 包

  1. java、jsp
  2. struts2 以及相关 jar 包
  3. Qrcode.jar
  4. 文件上传相关 jar 包
  • 自己编写摸索出来的艺术二维码算法
  • 响应式

实现流程

因为要实现精美艺术二维码,把黑白二维码的黑色部分,点状部分替换成有颜色的点,汇聚成一张精美的二维码

那么实现的关键点就是:替换

将制作好的小图片素材,按照编号命名,三个码眼使用大图片素材,其他使用不相同小图片素材,绘制二维码图片的时候,将画笔改为将插入图片素材 drawImage

根据不同类型的艺术二维码(不同的素材),使用不同的算法

话不多说,上代码

/**
* QrcodeText 二维码
* @author krry
* @version 1.0
*
*/
public class QrcodeText{ private static int width = 975;
private static int height = 975; // 设置偏移量,不设置可能导致解析出错
private static int pixoff = 25;
// 像素大小
private static int pix = 25;
// 二维码数组的长度
private static int codeLength;
// 随机数,生成[0,2]之间的随机整数,取长度为3的数组下标
private static int max = 3; //素材图片容器
private static BufferedImage image_eye;
private static BufferedImage image11;
private static BufferedImage image12;
private static BufferedImage image13;
private static BufferedImage image21;
private static BufferedImage image22;
private static BufferedImage image23;
private static BufferedImage image31;
private static BufferedImage image32;
private static BufferedImage image33;
private static BufferedImage image41;
private static BufferedImage image42;
private static BufferedImage image43; /**
* 生成二维码
* @param message 二维码内容
* @param type 二维码类型 如:锁屏
* @param filename 二维码类型下的标号 如1
* @param arti 使用算法类型 如0 热门
* @param transparent 是否透明 1:透明 0背景是白色
* @param request 请求
* @return
*/
public static String qrcode(String message,String type,String filename,String arti,String transparent,HttpServletRequest request){
String pathName = null;
FileOutputStream outputStream = null; try{
//创建二维码对象
Qrcode qrcode = new Qrcode();
//设置二维码的纠错级别
//L(7%) M(15%) Q(25%) H(30%)
qrcode.setQrcodeErrorCorrect('L'); //一般纠错级别小一点
//设置二维码的编码模式 Binary(按照字节编码模式)
qrcode.setQrcodeEncodeMode('B');
//设置二维码的版本号 1-40 1:20*21 2:25*25 40:177*177
qrcode.setQrcodeVersion(5); //获取图片缓存流对象
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphics2D gs = image.createGraphics(); //判断是否使用二维码背景颜色是透明
if(transparent.equals("yes")){
//设置透明
image = gs.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
gs = image.createGraphics();
} else {
gs.setBackground(Color.WHITE);
gs.clearRect(0, 0, width, height);
} //设置内容
String content = message;
byte[] contentsBytes = content.getBytes("utf-8"); //二维码
boolean[][] code = qrcode.calQrcode(contentsBytes);
//获取二维码数组的长度
codeLength = code.length; //码眼部分全部设置为false
for(int i=0;i<7;i++){
for(int j=0;j<7;j++){
code[i][j]=false;
}
for(int j=codeLength-7;j<codeLength;j++){
code[i][j]=false;
code[j][i]=false;
}
} //获取资源地址
String aspath = request.getServletContext().getRealPath("/resource"); //加载图片
loadImage(aspath,type,filename); //绘制二维码,选择算法
if(arti.equals("0")) drawQrcodeHot(gs, code); //热门算法
else if(arti.equals("1")) drawQrcodeOrdi(gs, code); //最初算法
else if(arti.equals("2")) drawQrcodeRiTojiao(gs, code); //三角算法 //如果类型不是单码,则装载背景图片,将二维码写进背景图片中,只有单码没有背景
if(!type.equals("dan")){
//装载背景图片
BufferedImage imageBG = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\bg.jpg"));
//获取背景图片的画笔
Graphics2D bg = imageBG.createGraphics(); //位置坐标
int x = 0;
int y = 0; //如果类型是方形,判断二维码在背景图片的位置,单码图片缩小到640像素
if(type.equals("fang")){
x = (imageBG.getWidth() - 640) / 2;
y = (imageBG.getHeight() - 640) / 2;
}
//如果类型是名片,判断二维码在背景图片的位置,单码图片缩小到640像素
if(type.equals("ming")){
x = (imageBG.getWidth() - 100) / 2;
y = (imageBG.getHeight() - 640) / 2;
}
//如果类型是锁屏,判断二维码在背景图片的位置,单码图片缩小到640像素
if(type.equals("suo")){
x = (imageBG.getWidth() - 640) / 2;
y = (imageBG.getHeight() - 1100) / 2;
} //将单码图片写进背景图片中,单码图片缩小到640像素
bg.drawImage(image, x, y, 640, 640, null); //释放画笔
bg.dispose();
gs.dispose();
//生成二维码图片
String realPath = request.getRealPath("/");
//String realPath = 服务器项目的地址;
pathName = new Date().getTime()+".jpg";
outputStream = new FileOutputStream(new File(realPath+"upload\\", pathName));
ImageIO.write(imageBG, "jpg", outputStream); } else { //如果类型是单码,直接释放输出
//释放画笔
gs.dispose();
//生成二维码图片
String realPath = request.getRealPath("/");
//String realPath = 服务器项目的地址;
pathName = new Date().getTime()+".png";
outputStream = new FileOutputStream(new File(realPath+"upload\\", pathName));
ImageIO.write(image, "png", outputStream);
}
} catch (Exception e){
e.printStackTrace();
} finally {
try {
//关闭流
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return pathName;
} /**
* 加载图片素材
* @param aspath
* @param type
* @param filename
*/
public static void loadImage(String aspath,String type,String filename){
try {
//加载码眼
image_eye = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\eye.png"));
//装载50*50的图片素材
image11 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\11.png"));
image12 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\12.png"));
image13 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\13.png"));
//装载100*50的图片素材
image21 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\21.png"));
image22 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\22.png"));
image23 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\23.png"));
//装载50*100的图片素材
image31 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\31.png"));
image32 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\32.png"));
image33 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\33.png"));
//装载100*100的图片素材
image41 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\41.png"));
image42 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\42.png"));
image43 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\43.png")); } catch (Exception e) {
e.printStackTrace();
}
} /**
* 绘制 算法0 热门二维码 素材有50*50 50*100 100*50 100*100
* @param gs 画笔
* @param code 二维码数组
*/
public static void drawQrcodeHot(Graphics2D gs,boolean[][] code){
//把图片素材放进数组
BufferedImage[] img1 = {image11,image12,image13};
BufferedImage[] img2 = {image21,image22,image23};
BufferedImage[] img3 = {image31,image32,image33};
BufferedImage[] img4 = {image41,image42,image43}; //通用地绘制码眼
gs.drawImage(image_eye, pix, pix, pix*7, pix*7, null);
gs.drawImage(image_eye, (codeLength-7)*pix+pixoff, pix, pix*7, pix*7, null);
gs.drawImage(image_eye, pix, (codeLength-7)*pix+pixoff, pix*7, pix*7, null); Random random = new Random(); // 绘制
for (int i = 0; i < codeLength; i++) {
for (int j = 0; j < codeLength; j++) {
if (code[i][j]) {
if (i+1 < codeLength && j+1 < codeLength && code[i][j + 1] && code[i + 1][j + 1] && code[i + 1][j]){
//随机取图片,画100*100的图
int s4 = random.nextInt(max);
gs.drawImage(img4[s4], i * pix + pixoff, j * pix + pixoff, pix * 2, pix * 2, null);
code[i][j + 1] = code[i + 1][j] = code[i + 1][j + 1] = false;
} else if(j+1 < codeLength && code[i][j+1]){
//随机取图片,画50*100的图
int s3 = random.nextInt(max);
gs.drawImage(img3[s3], i * pix + pixoff, j * pix + pixoff, pix, pix*2, null);
code[i][j+1] = false;
} else if (i+1 < codeLength && code[i+1][j]) {
//随机取图片,画100*50的图
int s2 = random.nextInt(max);
gs.drawImage(img2[s2], i * pix + pixoff, j * pix + pixoff, pix * 2, pix, null);
code[i+1][j] = false;
} else {
//随机取图片,画50*50的图
int s1 = random.nextInt(max);
gs.drawImage(img1[s1], i * pix + pixoff, j * pix + pixoff, pix, pix, null);
}
}
}
}
} /**
* 绘制 算法2 二维码 素材有50*50 50*100 100*50 100*100 其中100*100是三个角的算法,右上角没有填充
* @param gs 画笔
* @param code 二维码数组
*/
public static void drawQrcodeRiTojiao(Graphics2D gs,boolean[][] code){
System.out.println("三角啊");
//把图片素材放进数组
BufferedImage[] img1 = {image11,image12,image13};
BufferedImage[] img2 = {image21,image22,image23};
BufferedImage[] img3 = {image31,image32,image33};
BufferedImage[] img4 = {image41,image42,image43}; //通用地绘制码眼
gs.drawImage(image_eye, pix, pix, pix*7, pix*7, null);
gs.drawImage(image_eye, (codeLength-7)*pix+pixoff, pix, pix*7, pix*7, null);
gs.drawImage(image_eye, pix, (codeLength-7)*pix+pixoff, pix*7, pix*7, null); Random random = new Random(); // 绘制
for (int i = 0; i < codeLength; i++) {
for (int j = 0; j < codeLength; j++) {
if (code[i][j]) {
if (i+1 < codeLength && j+1 < codeLength && code[i][j + 1] && code[i + 1][j + 1]){
//随机取图片,画100*100的图 右上角没有填充
int s4 = random.nextInt(max);
gs.drawImage(img4[s4], i * pix + pixoff, j * pix + pixoff, pix * 2, pix * 2, null);
code[i][j + 1] = code[i + 1][j + 1] = false;
} else if(j+1 < codeLength && code[i][j+1]){
//随机取图片,画50*100的图
int s3 = random.nextInt(max);
gs.drawImage(img3[s3], i * pix + pixoff, j * pix + pixoff, pix, pix*2, null);
code[i][j+1] = false;
} else if (i+1 < codeLength && code[i+1][j]) {
//随机取图片,画100*50的图
int s2 = random.nextInt(max);
gs.drawImage(img2[s2], i * pix + pixoff, j * pix + pixoff, pix * 2, pix, null);
code[i+1][j] = false;
} else {
//随机取图片,画50*50的图
int s1 = random.nextInt(max);
gs.drawImage(img1[s1], i * pix + pixoff, j * pix + pixoff, pix, pix, null);
}
}
}
}
} /**
* 绘制 算法1 普通二维码 素材有50*50 50*100 50*150
* @param gs 画笔
* @param code 二维码数组
*/
public static void drawQrcodeOrdi(Graphics2D gs,boolean[][] code){
//把图片素材放进数组
BufferedImage[] img1 = {image11,image12,image13};
BufferedImage[] img2 = {image21,image22,image23};
BufferedImage[] img3 = {image31,image32,image33}; //通用地绘制码眼
gs.drawImage(image_eye, pix, pix, pix*7, pix*7, null);
gs.drawImage(image_eye, (codeLength-7)*pix+pixoff, pix, pix*7, pix*7, null);
gs.drawImage(image_eye, pix, (codeLength-7)*pix+pixoff, pix*7, pix*7, null); Random random = new Random(); for(int i = 0;i < codeLength;i++){
for(int j = 0;j < codeLength;j++){
//1*3
if(code[i][j]){
if(i+2 < codeLength && code[i+1][j] && code[i+2][j]){
//随机取图片 下标随机[0,2],画50*150的图
int s3 = random.nextInt(max);
gs.drawImage(img3[s3], j*25+pixoff, i*25+pixoff, 25, 75, null);
code[i+2][j]=false;
code[i+1][j]=false;
}else if(i+1 < codeLength && code[i+1][j]){
//1*2
//随机取图片,画50*100的图
int s2 = random.nextInt(max);
gs.drawImage(img2[s2], j*25+pixoff, i*25+pixoff, 25, 50, null);
code[i+1][j]=false;
} else {
//随机取图片,画50*50的图
int s1 = random.nextInt(max);
gs.drawImage(img1[s1], j*25+pixoff, i*25+pixoff, 25, 25, null);
}
}
}
}
}
}

项目截图

说明

  1. 以下截图的项目,生成二维码的价格均是测试用例,并不会真的需要支付.....
  2. 目前只实现单码的艺术二维码生成,其他暂不支持~~
  3. 除了单码,其他二维码样例图片取自第九工场







相关地址

项目地址:https://www.ainyi.com/krry_AiQrcode

GitHub:https://github.com/Krryxa/krry_AiQrcode

欢迎 start

krryblog:https://ainyi.com

博客地址:https://ainyi.com/58

分享:Java 开发精美艺术二维码的更多相关文章

  1. Java生成艺术二维码也可以很简单

    原文点击: Quick-Media Java生成艺术二维码也可以很简单 现在二维码可以说非常常见了,当然我们见得多的一般是白底黑块,有的再中间加一个 logo,或者将二维码嵌在一张特定的背景中(比如微 ...

  2. 通通WPF随笔(3)——艺术二维码素材生成器

    原文:通通WPF随笔(3)--艺术二维码素材生成器 最近公司让我开发一个条形码的生成控件,花了半天时间搞定觉得不过瘾,什么年代了该用二维码了吧.于是wiki了一下二维码的资料. 比较常见的就是QR码( ...

  3. iOS开发-定制多样式二维码

    iOS开发-定制多样式二维码   二维码/条形码是按照某种特定的几何图形按一定规律在平台(一维/二维方向上)分布的黑白相间的图形纪录符号信息.使用若干个与二进制对应的几何形体来表示文字数值信息. 最常 ...

  4. Android开发——通过扫描二维码,打开或者下载Android应用

    Android开发——通过扫描二维码,打开或者下载Android应用   在实现这个功能的时候,被不同的浏览器折磨的胃疼,最后实现了勉强能用,也查考了一下其他人的博客 android实现通过浏览器点击 ...

  5. Java根据链接生成二维码

    Java根据链接生成二维码 相关 jar 包: core-3.1.0.jar 源码及 jar 包下载:http://files.cnblogs.com/files/liaolongjun/qrcode ...

  6. java学习-zxing生成二维码矩阵的简单例子

    这个例子需要使用google的开源项目zxing的核心jar包 core-3.2.0.jar 可以百度搜索下载jar文件,也可使用maven添加依赖 <dependency> <gr ...

  7. Java后台直接生成二维码介绍

    Java后台直接生成二维码 1.其实jquery也可以直接生成二维码的,但我测试的时候,二维码生成后太模糊,难以识别.所以在这里介绍在后来生成二维码的方式. 2.不善于文字描述,直接上代码了. imp ...

  8. Java生成名片式的二维码源码分享

    世界上25%的人都有拖延症——但我觉得这统计肯定少了,至少我就是一名拖延症患者.一直想把“Java生成名片式(带有背景图片.用户网络头像.用户昵称)的二维码”这篇博客分享出来,但一直拖啊拖,拖到现在, ...

  9. 如何使用Java、Servlet创建二维码

    归功于智能手机,QR码逐渐成为主流,它们正变得越来越有用.从候车亭.产品包装.家装卖场.汽车到很多网站,都在自己的网页集成QR码,让人们快速找到它们.随着智能手机的用户量日益增长,二维码的使用正在呈指 ...

随机推荐

  1. nvidia-smi GPU异常消失 程序中断

    GPU型号为NVIDIA的1080Ti,最近出现的状况的是某一个GPU突然就出问题了,如果在该GPU上有运行程序的话则程序中断,nvidia-smi显示出来的GPU则少了这一个. 1.一开始怀疑是温度 ...

  2. C语言复习5_调试

    使用CodeBlocks调试程序 首先要注意,只有打开projects(.cbp文件)的情况下才能debug,单独打开.c文件是不能debug的 1.在行号旁边左键,出现红点,表示为断点breakpo ...

  3. Mesos源码分析(1): Mesos的启动过程总论

  4. 最快效率求出乱序数组中第k小的数

    题目:以尽量高的效率求出一个乱序数组中按数值顺序的第k 的元素值 思路:这里很容易想到直接排序然后顺序查找,可以使用效率较高的快排,但是它的时间复杂度是O(nlgn),我们这里可以用一种简便的方法,不 ...

  5. Angular ui-roter 和AngularJS 通过 ocLazyLoad 实现动态(懒)加载模块和依赖

    什么是ui-router ui-router是AngularUI库最有用的组件之一(AngularUI库由AngularJS社区构建).它是一个第三方路由框架,允许通过状态机制组织接口,而不是简单的U ...

  6. [Swift]LeetCode46. 全排列 | Permutations

    Given a collection of distinct integers, return all possible permutations. Example: Input: [1,2,3] O ...

  7. [Swift]LeetCode543. 二叉树的直径 | Diameter of Binary Tree

    Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a b ...

  8. [Swift]LeetCode676. 实现一个魔法字典 | Implement Magic Dictionary

    Implement a magic directory with buildDict, and search methods. For the method buildDict, you'll be ...

  9. [Swift]LeetCode704. 二分查找 | Binary Search

    Given a sorted (in ascending order) integer array nums of nelements and a target value, write a func ...

  10. Python—day13 迭代器、迭代器对象、for循环对象、生成器、枚举对象

    一.迭代器 1.迭代器概念: 器:包含了多个值的容器 迭代:循环反馈(一次从容器在取出一个值) 迭代器:从装有多个值的容器在一次取出一个值 ls=[3,5,7,1,9] 遍历:被遍历的对象必须是有序容 ...