2016年1月29日 星期五

QRCode with Logo Java Sample

注意事項:
    1. 此範例使用 Maven 建置相關內容請另行查閱
    2. 文章內容僅供參考

目錄

檔案配置

JavaSample
|____main
| |____java
| | |____sample
| |   |____qrcode
| |     |____QRCodeUtils.java
| |     |____SampleMain.java
| |____resources
|   |____qrcode-logo.png
|____output.png
|____pom.xml

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>tw.cookie.project</groupId>
    <artifactId>JavaSample</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <zxing.version>3.1.0</zxing.version>
    </properties>

    <dependencies>
        <!-- Official ZXing ("Zebra Crossing") -->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>${zxing.version}</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>${zxing.version}</version>
        </dependency>
    </dependencies>
</project>

QRCodeUtils

package sample.qrcode;

import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

import static com.google.zxing.BarcodeFormat.QR_CODE;

/**
 * Created by Cookie on 16/1/30.
 */
public class QRCodeUtils {
    private static final String IMAGE_FORMAT = "png";

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

    private static final int WIDTH = 256;
    private static final int HEIGHT = 256;

    private static final String FRONT_IMAGE_NAME = "qrcode-logo.png";
    private static final BufferedImage FRONT_IMG;
    private static final int FRONT_IMG_START_X;
    private static final int FRONT_IMG_START_Y;

    private static final QRCodeWriter WRITER = new QRCodeWriter();

    static {
        InputStream inputStream = null;
        BufferedInputStream headBIS = null;
        BufferedImage image = null;
        int start_x = 0;
        int start_y = 0;
        try {
            inputStream = ClassLoader.getSystemResourceAsStream(FRONT_IMAGE_NAME);
            headBIS = new BufferedInputStream(inputStream);
            image = ImageIO.read(headBIS);

            start_x = (WIDTH - image.getWidth()) /2;
            start_y = (HEIGHT - image.getHeight()) /2;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (headBIS != null) {
                try {
                    headBIS.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        FRONT_IMG = image;
        FRONT_IMG_START_X = start_x;
        FRONT_IMG_START_Y = start_y;
    }

    public static ByteArrayOutputStream encode(String content) {
        ByteArrayOutputStream result = null;
        try {
            BitMatrix matrix = WRITER.encode(content, QR_CODE, WIDTH, HEIGHT);
            result = new ByteArrayOutputStream();
            MatrixToImageWriter.writeToStream(matrix, IMAGE_FORMAT, result);
        } catch (Exception e) {
            e.printStackTrace();
            close(result);
        }
        return result;
    }

    public static ByteArrayOutputStream encodeWithLogo(String content) {
        if (FRONT_IMG == null) {
            return encode(content);
        }
        ByteArrayOutputStream result = null;
        try {
            BitMatrix matrix = WRITER.encode(content, QR_CODE, WIDTH, HEIGHT);
            BufferedImage backImage = QRCodeUtils.toBufferedImage(matrix);

            Graphics2D g = backImage.createGraphics();
            g.drawImage(FRONT_IMG, FRONT_IMG_START_X, FRONT_IMG_START_Y, null);

            result = new ByteArrayOutputStream();
            if(!ImageIO.write(backImage, IMAGE_FORMAT, result)) {
                throw new IOException("Could not write an image of format png.");
            }
        } catch (Exception e) {
            e.printStackTrace();
            close(result);
        }
        return result;
    }

    private static BufferedImage toBufferedImage(BitMatrix matrix) {
        int w = matrix.getWidth();
        int h = matrix.getHeight();
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }

    private static void close(Closeable obj) {
        if (obj == null) return;
        try {
            obj.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Sample Main

package sample.qrcode;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;

/**
 * Created by Cookie on 16/1/30.
 */
public class SampleMain {
    public static void main(String[] args) throws Exception {
        ByteArrayOutputStream stream = QRCodeUtils.encodeWithLogo(
            "http://tsai-cookie.blogspot.com/2016/01/qrcode-with-logo-java-sample.html");
        if (stream == null) throw new RuntimeException("Create QRCode Failed.");
        FileOutputStream out = new FileOutputStream("output.png");
        out.write(stream.toByteArray());
        stream.close();
        out.close();
    }
}

成果

2016年1月18日 星期一

淺談 CookieTsai 的程式設計

注意事項:
    1. 內容僅是自身經驗之分享,如有雷同純屬巧合。
    2. 僅供參考與學習使用,如有其他用途請告知。

目錄

文章簡介

小編是一名 Java 程式設計師,有一日結識了一名想透過小編學習寫程式的外國人。由於小編的英文程度相當令人堪憂,在語言不易溝通的情況下,大多只能分享自身對程式設計的理念與方針,所幸幾次下來也整理出了一些知識,最後整理成這篇文章。

程式設計

  • 目的
    寫一個簡單程式的難度,小編認為可以把它當成寫一句英文(如:Hello World!!)來看待,不會很難也不需要很久的時間。程式語言既然稱之為語言就會有語法及特性,而其主要目的小編認為是用在人與電腦之間當溝通的媒介。
  • 特性
    程式語言由於要給人與電腦閱讀具有幾種特性,其中與一般語言最大的不同,大概會是語法必須是完全正確,正確的意思為可以通過編譯器(Compiler)而不出現錯誤。
  • 設計
    • Simple(為電腦而設計)
      一言以蔽之為精簡的程式碼,邏輯上要達到簡明扼要,除此外還要讓程式碼的長、寬、巢狀及遞迴...等結構減少,以效能達到最高為主要目的。
    • Stupid(為人而設計)
      軟體工程中消耗最多的就是維護的成本,可高達整個專案的 7成以上,撰寫人人都可以輕鬆閱讀的程式碼是 Stupid 最高的目標。
  • 學習
    基於以上種種原因及目的,如果期許自己能學好一門程式語言。除了最初的程式入門外,小編認為通過專案的實作與練習,以有特定目標來學習程式語言是最佳的方法。
  • 閱讀 vs 編寫
    在聽說讀寫中程式語言著重於讀與寫,而讀與寫中又極其偏重讀。在一般請況下,一個大型專案中自己所撰寫過的程式佔不到半數。許多程式是由其他夥伴甚至是第三方團體所提供,為了使專案能正常的運作,我們需要盡可能的不讓無法理解的內容加入到專案之中,因此閱讀他人所編寫的程式碼就變得極其重要。
  • 結語
    如何真的學好一門程式語言,實際上就跟學習其他語言相同,有一些基本語法需要記憶。但更重要的是通過團隊實作來證實所學,在實作過程中電腦可以讓你知道,所學的語法是正確的,而團隊夥伴可以讓你知道撰寫的程式是否簡明扼要。