因行動裝置的流行而跟著帶動起來的QR Code,是眾多條碼類型的其中一種,它讓我們的生活更便利,傳遞資訊的速度更快,省下許多使用鍵盤打字的時間。如果要產生出QR Code,已經有許多相關的現成工具能夠使用,甚至還能直接在網頁上產生。只是有的時候還是會遇到需要在自己的程式中加入產生QR Code的狀況,像是需要產生大量的QR Code時,或是想要讓自己的程式能不依賴其他工具就能獨立使用。這篇文章,將會探討如何使用Java程式語言產生QR Code。當然,因為是Java程式,因此在Android SDK上也是可以用的。



從以上連結可以直接取得用Java語言寫的QR Code Library,另外還有提供PHP以及Ruby的版本。這個Library用了許多檔案來存了不同大小以及不同容錯率的QR Core所使用的資料,算是有點小肥。在使用這個Java版本的Library的時候,會發現有許多不知道是在做什麼用的API,因此筆者另外寫了MagicQRCode函式庫來取代官方的,使用起來會簡單很多。MagicQRCode可以至GitHub取得:

MagicQRCode函式庫的使用方法十分簡單,只要兩行就可以產生出QR Code:

QRCodeEncoder qr = new QRCodeEncoder("QR Code的內容");
boolean[][] qrData = qr.encode();

也可以多加一行setErrorCorrect方法,來設定QR Code的容錯率。愈高的容錯率資料量將愈大,但可以有效避免當條碼模糊不清,或是有部份受損時,造成無法辨識的情形。

QRCodeEncoder qr = new QRCodeEncoder("QR Code的內容");
qr.setErrorCorrect(QRCodeEncoder.ErrorCorrect.MAX);
boolean[][] qrData = qr.encode();

qrData是一個二維的boolean陣列,陣列的大小會根據編碼的文字長度和容錯率而有所變動,但這個陣列一定是個方形陣列(長度相同)。如果要將qrData轉成我們平常看到由黑白兩色組成的圖片,可以參考以下程式碼,將其會製成圖形:

JavaFX繪製QR Code
public static void drawQRCode(final Canvas canvas, final boolean[][] qrData) {
    final int width = (int)canvas.getWidth();
    final int height = (int)canvas.getHeight();
    final GraphicsContext gc = canvas.getGraphicsContext2D();

    //畫背景(全白)
    gc.setFill(Color.WHITE);
    gc.fillRect(0, 0, width, height);

    final int imageSize = Math.min(width, height);
    final int length = qrData.length;
    final int size = imageSize / length;
    final int actualImageSize = size * length;
    final int offsetImageX = (width - actualImageSize) / 2;
    final int offsetImageY = (height - actualImageSize) / 2;

    //畫資料(true為黑色)
    gc.setFill(Color.BLACK);
    for (int i = 0; i < length; i++) {
        for (int j = 0; j < length; j++) {
            if (qrData[i][j]) {
                final int x = i * size + offsetImageX;
                final int y = j * size + offsetImageY;
                gc.fillRect(x, y, size, size);
            }
        }
    }
}

Android SDK繪製QR Code
public static void drawQRCode(final Canvas canvas, final boolean[][] qrData) {
    final Paint paint = new Paint();
    final int width = canvas.getWidth();
    final int height = canvas.getHeight();
    
    //畫背景(全白)
    paint.setColor(Color.WHITE);
    canvas.drawRect(new Rect(0, 0, width, height), paint);
    
    final int imageSize = Math.min(width, height);
    final int length = qrData.length;
    final int size = imageSize / length;
    final int actualImageSize = size * length;
    final int offsetImageX = (width - actualImageSize) / 2;
    final int offsetImageY = (height - actualImageSize) / 2;
    
    //畫資料(true為黑色)
    paint.setColor(Color.BLACK);
    for (int i = 0; i < length; i++) {
        for (int j = 0; j < length; j++) {
            if (qrData[i][j]) {
                final int x = i * size + offsetImageX;
                final int y = j * size + offsetImageY;
                canvas.drawRect(new Rect(x, y, x + size, y + size), paint);
            }
        }
    }
}