Androidアプリで1次元バーコードを作成する方法3

今回も前回に引き続き、ライブラリを使用せず1次元バーコードを作成・表示する方法を紹介する。
前回はライブラリを使用せず「CODABAR(NW-7)」規格のバーコードを作成・表示したが、今回は「CODE39」規格のバーコードを作成・表示する方法を紹介する。

「CODABAR」規格と「CODE39」規格を比較すると、特徴的なのは使用できる文字種類の数である。
「CODABAR」が基本的に「0〜9」の数字のみ(スタート/ストップキャラクタとして「A〜D」を使用できる)であるのに対し、「CODE39」は「0〜9,A〜Z,-,., (空白),$,/,+,%」の43種類の文字を使用することができる。
ただし、「CODE39」は「CODABAR」と比較して、バーコードの横幅が大きくなってしまうので、桁数の大きなデータをバーコードにした場合、バーコードリーダーの横幅より大きくなってしまい読み取れない事があるので注意が必要である。

「CODE39」と「CODABAR」の作成方法はよく似ているため、前回紹介した「CODABAR」を作成するためのクラスである「MyCodaBarWriter」をほぼ流用することができる。
「CODE39」を作成するためのクラス「MyCode39Writer」のソースコードを以下に示す。

MyCode39Writer.java

package biz.accele.samplebarcode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MyCode39Writer {

    //スタートキャラクタ、ストップキャラクタ(*固定)
    private final String START_CHAR = "*";
    private final String END_CHAAR  = "*";

    //バーコードの両端に設けるマージンサイズ(クワイエットゾーン)を棒幅の何個分かで指定する
    private final int SIDE_MARGIN_NUM = 10;

    //エレメントの値
    private final int WHITE = 0;     //白エレメント
    private final int BLACK = 1;     //黒エレメント

    //変換用情報(CODE39の仕様より作成)
    private final int[] convert0  = {BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK};
    private final int[] convert1  = {BLACK, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK};
    private final int[] convert2  = {BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK};
    private final int[] convert3  = {BLACK, BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK};
    private final int[] convert4  = {BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK};
    private final int[] convert5  = {BLACK, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK};
    private final int[] convert6  = {BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK};
    private final int[] convert7  = {BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, BLACK};
    private final int[] convert8  = {BLACK, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK};
    private final int[] convert9  = {BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK};
    private final int[] convertA  = {BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, BLACK};
    private final int[] convertB  = {BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, BLACK};
    private final int[] convertC  = {BLACK, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK};
    private final int[] convertD  = {BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, BLACK};
    private final int[] convertE  = {BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK};
    private final int[] convertF  = {BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK};
    private final int[] convertG  = {BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK, BLACK};
    private final int[] convertH  = {BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK};
    private final int[] convertI  = {BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK};
    private final int[] convertJ  = {BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK};
    private final int[] convertK  = {BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, BLACK};
    private final int[] convertL  = {BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, BLACK};
    private final int[] convertM  = {BLACK, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK};
    private final int[] convertN  = {BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, BLACK};
    private final int[] convertO  = {BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK};
    private final int[] convertP  = {BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK};
    private final int[] convertQ  = {BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK, BLACK};
    private final int[] convertR  = {BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK};
    private final int[] convertS  = {BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK};
    private final int[] convertT  = {BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, BLACK, WHITE, WHITE, BLACK};
    private final int[] convertU  = {BLACK, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK};
    private final int[] convertV  = {BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK};
    private final int[] convertW  = {BLACK, BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK};
    private final int[] convertX  = {BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK};
    private final int[] convertY  = {BLACK, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK};
    private final int[] convertZ  = {BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK};
    private final int[] convertHY = {BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, BLACK};   // -
    private final int[] convertPD = {BLACK, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK};   // .
    private final int[] convertSP = {BLACK, WHITE, WHITE, BLACK, BLACK, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK};   //  (空白)
    private final int[] convertDL = {BLACK, WHITE, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK};   // $
    private final int[] convertSL = {BLACK, WHITE, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK};   // /
    private final int[] convertPL = {BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, WHITE, BLACK};   // +
    private final int[] convertPC = {BLACK, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, WHITE, BLACK, WHITE, WHITE, BLACK};   // %
    private final int[] convertAS = {BLACK, WHITE, WHITE, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK, BLACK, WHITE, BLACK};   // *

    //変換用情報をMap型に格納する
    private final Map<String, Object> mapConvert = new HashMap<String, Object>(){
        {
            put("0", convert0);
            put("1", convert1);
            put("2", convert2);
            put("3", convert3);
            put("4", convert4);
            put("5", convert5);
            put("6", convert6);
            put("7", convert7);
            put("8", convert8);
            put("9", convert9);
            put("A", convertA);
            put("B", convertB);
            put("C", convertC);
            put("D", convertD);
            put("E", convertE);
            put("F", convertF);
            put("G", convertG);
            put("H", convertH);
            put("I", convertI);
            put("J", convertJ);
            put("K", convertK);
            put("L", convertL);
            put("M", convertM);
            put("N", convertN);
            put("O", convertO);
            put("P", convertP);
            put("Q", convertQ);
            put("R", convertR);
            put("S", convertS);
            put("T", convertT);
            put("U", convertU);
            put("V", convertV);
            put("W", convertW);
            put("X", convertX);
            put("Y", convertY);
            put("Z", convertZ);
            put("-", convertHY);
            put(".", convertPD);
            put(" ", convertSP);
            put("$", convertDL);
            put("/", convertSL);
            put("+", convertPL);
            put("%", convertPC);
            put("*", convertAS);
        }
    };

// ---  以降は前回の「MyCodaBarWriter」クラスと全く同一 -------------------------------------------

    public MyBitMatrix encode(String targetData, int width, int height){

        //スタートキャラクタ、ストップキャラクタの付与
        String exTargetData = START_CHAR + targetData + END_CHAAR;

        //データの変換
        List<Integer> codeArray = convertData(exTargetData);

        //バーコードデータの生成
        MyBitMatrix bitMatrix = createBarcode(codeArray, width, height);

        return bitMatrix;
    }

    // データを変換する
    private List<Integer> convertData(String targetData){

        List<Integer> resultArray = new ArrayList<>();

        //サイドマージン(左)
        for(int i=0; i<SIDE_MARGIN_NUM; i++){
            resultArray.add(WHITE);
        }


        //データ変換
        for(int i=0; i<targetData.length(); i++){

            // 先頭から1文字づつ取り出す
            String targetChar = targetData.substring(i, i+1);

            // 取り出した文字を変換する
            joinArray(resultArray, targetChar);

            // キャラクターギャップ
            resultArray.add(WHITE);
        }

        // 最後のキャラクターギャップを削除する
        resultArray.remove(resultArray.size() - 1);

        //サイドマージン(右)
        for(int i=0; i<SIDE_MARGIN_NUM; i++){
            resultArray.add(WHITE);
        }

        return resultArray;
    }

    //Listの末尾に文字を変換した情報を付け加える
    private void joinArray(List<Integer> resultArray, String targetChar){

        int[] targetArray = (int[])mapConvert.get(targetChar);

        for(int i=0; i<targetArray.length; i++){

            resultArray.add(targetArray[i]);
        }
    }

    //バーコード情報を生成する
    private MyBitMatrix createBarcode(List<Integer> targetData, int width, int height) {

        // バー幅の算出
        int multiple = getBarWidth(targetData.size(), width);

        // バーコード描画サイズの算出
        int drawPx = targetData.size() * multiple;

        // 要求幅に合わせるために必要な調整幅を算出する
        int leftSideAdjust  = (width - drawPx) / 2;

        // 結果を格納するためのBitMatrixをインスタンス化する
        MyBitMatrix output = new MyBitMatrix(width, height);

        // 制御変数の初期化
        int outputX = leftSideAdjust;

        for (int inputX = 0; inputX < targetData.size(); inputX++) {

            if (targetData.get(inputX).intValue() == BLACK) {

                output.setRegion(outputX, 0, multiple, height);
                outputX += multiple;

            }else{

                outputX += multiple;
            }
        }
        return output;
    }

    // 指定されたピクセル数を超えず、かつ最大限大きく描画するためにバー幅の最適値を算出する
    private int getBarWidth(int barCount, int viewWidth){

        int resultMultiple = 1;

        int multiple = 1;

        while(true){

            int px = barCount * multiple;

            if(px > viewWidth){

                break;

            }else{

                resultMultiple = multiple;
            }

            multiple += 1;
        }

        return resultMultiple;
    }
}

「MyCode39Writer」クラスを使用して、バーコードを作成・表示する方法は、前回の内容を参照のこと。

[実行結果]

f:id:MoonMtLab:20160922095943p:plain:w300

Enjoy Programing!!