2016/11/09 このエントリーをはてなブックマークに追加 はてなブックマーク - JavaでQRコードを作る。ついでにKotlinでも

JavaでQRコードを作る。ついでにKotlinでも

カテゴリ: ,




今日お昼ごはん食べてた時になんかこんなことやって遊んでたなーって話をして思い出した。
そういえば昔、JavaでQRコードを書きたくなったことがあったのでした。



そして、ブログを書こうとしていてずっと眠らせていたので何年か前のブログの書き損じを公開してみます。



ZXing ("zebra crossing") はオープンソースのmulti-format 1D/2DバーコードイメージのJava実装ライブラリで他の言語でも利用できるようです。
https://github.com/zxing/zxing


















zxingのサンプル。こんな感じで動きます。当時のプロジェクトがJava SE 7だったのでそんな感じの書きっぷりです。


package sample.yank.yy.zxing;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class Main {

    private final static int BLACK = 0xFF000000;
    private final static int WHITE = 0xFFFFFFFF;

    public static void main(String... args) throws IOException {
        new Runner().run();
    }

    static class Runner {

        private FileVisitor<Path> visitor = new FileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println(file.getFileName());
                if (file.toString().endsWith("png")) {
                    Files.delete(file);
                } else if(file.toString().endsWith("txt")){
                    StringBuilder builder = new StringBuilder();
                    List<String> lines = Files.readAllLines(file);
                    lines.forEach(builder::append);
                    textList.add(new Tuple(file, builder.toString()));
                }

                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                return FileVisitResult.CONTINUE;
            }
        };

        private List<Tuple> textList = new ArrayList<>();

        /**
         * runner.run 1. start. 2. file walking and collect file texts. 3.
         * encoding to qrcode for-each file 4. end
         */
        public void run() throws IOException {

            System.out.println("[START]");
            Files.walkFileTree(Paths.get("/", "Users", "yank", "Desktop", "test"), visitor);
            for (Tuple t : textList) {
                createQrCode(t.key, t.value);
            }

            System.out.println("[END]");
        }

        /**
         * create png file to draw qr-code.
         * 
         * @param filePath
         *            path.
         * @param contents
         *            text.
         */
        private void createQrCode(Path filePath, String contents) {
            try {
                BarcodeFormat format = BarcodeFormat.QR_CODE;
                int width = 300;
                int height = 300;

                Map<EncodeHintType, Object> hints = new HashMap<>();
                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
                hints.put(EncodeHintType.CHARACTER_SET, "Shift-JIS");

                QRCodeWriter writer = new QRCodeWriter();
                BitMatrix bitMatrix = writer.encode(contents, format, width, height, hints);

                int[] agbArray = createRgbArray(width, height, bitMatrix);

                BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                qrImage.setRGB(0, 0, width, height, agbArray, 0, width);
                qrImage.flush();
                ImageIO.write(qrImage, "png", new File(filePath.toString() + ".png"));
            } catch (IOException | WriterException e) {
                System.err.println(e.getMessage() + " : filePath......." + filePath.toString());
            }
        }

        private int[] createRgbArray(int width, int height, BitMatrix bitMatrix) {
            int[] pixels = new int[width * height];
            // All are 0, or black, by default
            for (int y = 0; y < height; y++) {
                int offset = y * width;
                for (int x = 0; x < width; x++) {
                    pixels[offset + x] = bitMatrix.get(x, y) ? BLACK : WHITE;
                }
            }
            return pixels;
        }
    }
}

/**
 * tuple
 */
class Tuple {
    public Path key;
    public String value;

    Tuple(Path key, String value) {
        this.key = key;
        this.value = value;
    }
}




こいつを使うとこんなふうにQRコードが出来上がるのです。















これだけじゃ味気ないかなーってことでKotlinでも書いてみました。こんな感じになります。

/**
 * Created by yy_yank on 2016/11/09.
 */
object KtRunner {
    val textList = mutableListOf<Pair<Path, String>>()
    val visitor = object : FileVisitor<Path> {
        override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult = FileVisitResult.CONTINUE
        override fun visitFile(file: Path, attrs: BasicFileAttributes) : FileVisitResult = FileVisitResult.CONTINUE.apply {
            println(file.fileName)
            when {
                file.toString().endsWith("png") -> Files.delete(file)
                file.toString().endsWith("txt") -> {
                    val lines = Files.readAllLines(file)
                    textList.add(Pair(file, lines.reduce { s1, s2 -> s1 + s2 }))
                }
            }
        }
        override fun visitFileFailed(file: Path, exc: IOException): FileVisitResult = FileVisitResult.CONTINUE
        override fun postVisitDirectory(dir: Path, exc: IOException): FileVisitResult = FileVisitResult.CONTINUE
    }
    @JvmStatic fun main(args: Array<String>) {
        println("[START]")
        val url = Thread.currentThread().contextClassLoader.getResource("test.txt")
        Files.walkFileTree(Paths.get(url!!.toURI()), visitor)
        textList.forEach { KtQrCodeDrawer.draw(it) }
        println("[END]")
    }
}





特に見どころはないです。














https://github.com/yyYank/zxing-sample/





0 件のコメント:

コメントを投稿

GA