带动态背景图的二维码生成器

简介: BitQR-Code Through image generate QR-Code . 一个优雅的 QR 二维码生成器 Github项目地址 : https://github.com/CasterWx/BitQR-Code 样例 拿起你的手机扫描下面的二维码试试吧! 原图 Version-3 .

BitQR-Code

Through image generate QR-Code .

一个优雅的 QR 二维码生成器

Github项目地址 : https://github.com/CasterWx/BitQR-Code


样例

拿起你的手机扫描下面的二维码试试吧!

原图 Version-3
1.jpg out.png

| Version-5 | 直接拼凑GIF | 分解生成 |
| ------------ | ------------- | ------------ |
| out1.png | 1.gif | getgif.gif |

原图1 原图2 原图3
gif1.gif gif2.gif gif3.gif
GIF1 GIF2 GIF3
gif1-get.gif gif2-get.gif gif3-get.gif

GIF分解为多个帧

原GIF 第四帧 第七帧 第十帧
marry.gif P3.png P6.png P11.png
第十三帧 第十六帧 第二十帧 生成GIF
P12.png P15.png P19.png getgif.gif

2018年最后一天的最后一篇

引用

在项目中导入 QRCode.jar 以添加依赖:

<component name="libraryTable">
  <library name="QRCode">
    <CLASSES>
      <root url="jar://$PROJECT_DIR$/src/lib/QRCode.jar!/" />
    </CLASSES>
    <JAVADOC />
    <SOURCES />
  </library>
</component>

快速上手

1. "快速导入背景图片"

只想显示一张麻衣学姐的照片

BufferedImage writeImg = ImageIO.read(new File("麻衣学姐.jpg"));
BufferedImage bf = new BufferedImage(writeImg.getWidth(),writeImg.getHeight(),BufferedImage.TYPE_INT_RGB);
Graphics2D gs = bf.createGraphics() ;
gs.clearRect(0,0,bf.getWidth(),bf.getHeight());
gs.drawImage(writeImg,0,0,bf.getWidth(),bf.getHeight(),null);

writeImg是读取到的图片,然后根据这张照片创建Graphics的大小。

gs.drawImage(writeImg,0,0,bf.getWidth(),bf.getHeight(),null);

便可以将writeImg绘制到Graphics中了。

File imagefile = new File(imgPath);
ImageIO.write(bf,"png",imagefile);

现在就可以利用ImageIO将图片存储到本地了

效果
1.jpg

2. "图片中使用画笔"

Graphics2D gs = bf.createGraphics() ;
gs.setBackground(Color.white);
gs.clearRect(0,0,bf.getWidth(),bf.getHeight());
gs.drawImage(writeImg,0,0,bf.getWidth(),bf.getHeight(),null);

gs是创建出的画布,setBackground可以设置其背景色,也可以直接drawImage()将图片绘制进去。

gs.setColor(Color.BLACK);
gs.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,1.0f));
gs.fillRect(j*mini+begin,i*mini+begin,mini,mini );
  • setColor用于设置画笔颜色。
  • setComposite用于设置透明度
  • fillRect是绘制动作,参数值为起始坐标和结束坐标。

3. "二维码的本质是_______"

二维码的本质是二进制表示数据

二维码的黑白格,其实就代表了0和1两位数据,我们只需要将数据转化为bytes数组,然后根据数组的0-1值直接绘制到图片上,即可生成相应的二维码。

byte []contentByte = "需要表示的数据".getBytes("utf-8");
boolean [][]cidesOut = qrcode.calQrcode(contentByte) ;

这样就可以生成一个cidesOut数组来表示二维码的黑白格。

qrcode是二维码的生成配置,容错率和Qrcode版本等。

Qrcode qrcode = new Qrcode();
qrcode.setQrcodeErrorCorrect('M');
qrcode.setQrcodeEncodeMode('B');
qrcode.setQrcodeVersion(3);

4. "黑白格衬衫!!!"

二维码的本质是黑白格衬衫!!!

双层for循环遍历cidesOut这个boolean数组,如果是true就绘制黑色。

 for(int i=0;i<cidesOut.length;i++){
    for(int j=0;j<cidesOut.length;j++){
        if(cidesOut[j][i]){
            gs.fillRect(j*mini+begin,i*mini+begin,mini,mini );
        }
    }
}

GIF动画帧绘制

1. "如何绘制一个GIF"

AnimatedGifEncoder e = new AnimatedGifEncoder();
e.setRepeat(0);
e.start(newPic);
BufferedImage src[] = new BufferedImage[pic.length];
for (int i = 0; i < src.length; i++) {
    e.setDelay(playTime); 
    src[i] = ImageIO.read(new File(pic[i])); 
    e.addFrame(src[i]);  //添加到帧中
}
e.finish();

首先定义一个GIF生成类.

AnimatedGifEncoder e = new AnimatedGifEncoder();

e.start(newPic);

newPic代表最后生成的gif文件名.

e.setDelay(playTime);

设置播放的延迟时间playTime.

e.setDelay(playTime);

src[i] = ImageIO.read(new File(pic[i]));
e.addFrame(src[i]);

最后将BufferedImage图片添加到帧中.

e.finish();

GIF
1.gif

2. "如何分解一个GIF"

  • 加载gif
GifDecoder gd = new GifDecoder();//要处理的图片
int status = gd.read(new FileInputStream(new File("marry.gif")));
if (status != GifDecoder.STATUS_OK) {
  return;
}
  • GIF帧数为gd.getFrameCount();

我们可以直接获取每一帧的图片并且保存到本地。

for (int i = 0; i < gd.getFrameCount(); i++) {
  //取得gif的每一帧
  BufferedImage frame = gd.getFrame(i);
  // 存储frame到本地
}

可以将一个GIF分解成帧之后,我们就可以将这一帧添加二维码,然后加入到一个新的GIF中了。

  for (int i = 0; i < gd.getFrameCount(); i++) {
    //取得gif的每一帧
    BufferedImage frame = gd.getFrame(i);
    Graphics2D gs = frame.createGraphics() ;
    gs.drawImage(frame,0,0,frame.getWidth(),frame.getHeight(),null);
    int qrLength = frame.getHeight()-2*frame.getHeight()/10 ;
    int mini = qrLength/cidesOut.length ;
    int begin = (frame.getWidth() - mini*cidesOut.length)/2 ;
    for(int k=0;k<cidesOut.length;k++){
      for(int j=0;j<cidesOut.length;j++){
        if(cidesOut[j][k]){
          gs.setColor(Color.BLACK);
          gs.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,1.0f));
          gs.fillRect(j*mini+begin,k*mini+begin/4,mini,mini );
        }
      }
    }

  int delay = gd.getDelay(i);
  ge.setDelay(delay);
  ge.addFrame(frame);
原图 GIF
gif1.gif gif1-get.gif
原图 GIF
gif2.gif gif2-get.gif
原图 GIF
gif3.gif gif3-get.gif
目录
相关文章
|
文字识别 算法 数据挖掘
文本检测 DBNet
文本检测 DBNet
556 0
postman 传入不同组参数循环调用接口
postman 传入不同组参数循环调用接口
1680 0
postman 传入不同组参数循环调用接口
|
3月前
|
机器学习/深度学习 传感器 监控
基于多模态感知的工业安全行为识别技术突破
本项目通过分层特征增强架构,突破工业安全监控中微小目标检测难、行为理解缺失和响应延迟高等技术瓶颈。采用动态ROI聚焦、时空域建模与联邦学习等创新技术,实现厘米级行为捕捉,准确率提升300%,隐患识别响应速度提高112倍,并已在危化、电力、医疗等行业落地应用,具备广阔推广前景。
160 0
|
2月前
|
机器学习/深度学习 人工智能 算法
基于YOLO的中医舌苔自动识别系统 | 五类舌象精准检测【含完整数据+训练源码】
本项目以 YOLOv8 为核心检测引擎,实现了对中医舌象中五类舌苔特征的高效识别,构建了一个具有实用价值的中医智能辅助诊断系统原型。项目涵盖从数据准备、模型训练到推理部署的全流程,配套图形界面(可选),实现了开箱即用、模块清晰、易于复现的目标。
基于YOLO的中医舌苔自动识别系统 | 五类舌象精准检测【含完整数据+训练源码】
|
6月前
|
存储 Oracle 关系型数据库
MySQL 8.4 配置SSL组复制(八个步骤)
MySQL 8.4 配置SSL组复制(八个步骤)
373 0
|
8月前
|
关系型数据库 MySQL 数据库连接
Unity连接Mysql数据库 增 删 改 查
在 Unity 中连接 MySQL 数据库,需使用 MySQL Connector/NET 作为数据库连接驱动,通过提供服务器地址、端口、用户名和密码等信息建立 TCP/IP 连接。代码示例展示了如何创建连接对象并执行增删改查操作,确保数据交互的实现。测试代码中,通过 `MySqlConnection` 类连接数据库,并使用 `MySqlCommand` 执行 SQL 语句,实现数据的查询、插入、删除和更新功能。
|
Windows
Powershell 重新排列去重 Windows环境变量
【9月更文挑战第13天】本文介绍如何使用PowerShell对Windows环境变量进行重新排列和去重。首先通过`$env:`访问环境变量,接着使用`-split`命令分割路径,再利用`Select-Object -Unique`去除重复项。之后可根据需要对路径进行排序,最后将处理后的路径组合并更新环境变量。注意修改环境变量前应备份重要数据并了解潜在影响。
377 10
|
自然语言处理 运维 Cloud Native
运维大模型探索之 Text2PromQL 问答机器人
本文主要介绍将AIGC技术运用到可观测领域的探索。
1562 111
|
前端开发 JavaScript 中间件
【前端状态管理之道】React Context与Redux大对决:从原理到实践全面解析状态管理框架的选择与比较,帮你找到最适合的解决方案!
【8月更文挑战第31天】本文通过电子商务网站的具体案例,详细比较了React Context与Redux两种状态管理方案的优缺点。React Context作为轻量级API,适合小规模应用和少量状态共享,实现简单快捷。Redux则适用于大型复杂应用,具备严格的状态管理规则和丰富的社区支持,但配置较为繁琐。文章提供了两种方案的具体实现代码,并从适用场景、维护成本及社区支持三方面进行对比分析,帮助开发者根据项目需求选择最佳方案。
394 0