帶動態背景圖的二維碼生成器

奶berber發表於2019-01-01

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


相關文章