package com.google.zxing.qrcode.encoder;
import com.google.zxing.WriterException;
+import com.google.zxing.EncodeHintType;
import com.google.zxing.common.ByteArray;
import com.google.zxing.common.ByteMatrix;
import com.google.zxing.common.reedsolomon.GF256;
import com.google.zxing.qrcode.decoder.Version;
import java.util.Vector;
+import java.util.Hashtable;
import java.io.UnsupportedEncodingException;
/**
}
- // Encode "bytes" with the error correction level "getECLevel". The encoding mode will be chosen
- // internally by chooseMode(). On success, store the result in "qrCode" and return true.
- // We recommend you to use QRCode.EC_LEVEL_L (the lowest level) for
- // "getECLevel" since our primary use is to show QR code on desktop screens. We don't need very
- // strong error correction for this purpose.
- //
- // Note that there is no way to encode bytes in MODE_KANJI. We might want to add EncodeWithMode()
- // with which clients can specify the encoding mode. For now, we don't need the functionality.
+ /**
+ * Encode "bytes" with the error correction level "ecLevel". The encoding mode will be chosen
+ * internally by chooseMode(). On success, store the result in "qrCode".
+ *
+ * We recommend you to use QRCode.EC_LEVEL_L (the lowest level) for
+ * "getECLevel" since our primary use is to show QR code on desktop screens. We don't need very
+ * strong error correction for this purpose.
+ *
+ * Note that there is no way to encode bytes in MODE_KANJI. We might want to add EncodeWithMode()
+ * with which clients can specify the encoding mode. For now, we don't need the functionality.
+ */
public static void encode(String content, ErrorCorrectionLevel ecLevel, QRCode qrCode)
throws WriterException {
+ encode(content, ecLevel, null, qrCode);
+ }
+
+ public static void encode(String content, ErrorCorrectionLevel ecLevel, Hashtable hints, QRCode qrCode)
+ throws WriterException {
+
+ String characterEncoding = hints == null ? null : (String) hints.get(EncodeHintType.CHARACTER_SET);
+ if (characterEncoding == null) {
+ characterEncoding = "ISO-8859-1";
+ }
+
// Step 1: Choose the mode (encoding).
Mode mode = chooseMode(content);
// Step 2: Append "bytes" into "dataBits" in appropriate encoding.
BitVector dataBits = new BitVector();
- appendBytes(content, mode, dataBits);
+ appendBytes(content, mode, dataBits, characterEncoding);
// Step 3: Initialize QR code that can contain "dataBits".
int numInputBytes = dataBits.sizeInBytes();
initQRCode(numInputBytes, ecLevel, mode, qrCode);
}
}
- // Return the code point of the table used in alphanumeric mode. Return -1 if there is no
- // corresponding code in the table.
+ /**
+ * @return the code point of the table used in alphanumeric mode or
+ * -1 if there is no corresponding code in the table.
+ */
static int getAlphanumericCode(int code) {
if (code < ALPHANUMERIC_TABLE.length) {
return ALPHANUMERIC_TABLE[code];
return -1;
}
- // Choose the best mode by examining the content.
- //
- // Note that this function does not return MODE_KANJI, as we cannot distinguish Shift_JIS from
- // other encodings such as ISO-8859-1, from data bytes alone. For example "\xE0\xE0" can be
- // interpreted as one character in Shift_JIS, but also two characters in ISO-8859-1.
- //
- // JAVAPORT: This MODE_KANJI limitation sounds like a problem for us.
+ /**
+ * Choose the best mode by examining the content.
+ *
+ * Note that this function does not return MODE_KANJI, as we cannot distinguish Shift_JIS from
+ * other encodings such as ISO-8859-1, from data bytes alone. For example "\xE0\xE0" can be
+ * interpreted as one character in Shift_JIS, but also two characters in ISO-8859-1.
+ */
public static Mode chooseMode(String content) {
boolean hasNumeric = false;
boolean hasAlphanumeric = false;
return bestMaskPattern;
}
- // Initialize "qrCode" according to "numInputBytes", "ecLevel", and "mode". On success, modify
- // "qrCode".
+ /**
+ * Initialize "qrCode" according to "numInputBytes", "ecLevel", and "mode". On success, modify "qrCode".
+ */
private static void initQRCode(int numInputBytes, ErrorCorrectionLevel ecLevel, Mode mode, QRCode qrCode)
throws WriterException {
qrCode.setECLevel(ecLevel);
throw new WriterException("Cannot find proper rs block info (input data too big?)");
}
- // Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).
+ /**
+ * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).
+ */
static void terminateBits(int numDataBytes, BitVector bits) throws WriterException {
int capacity = numDataBytes << 3;
if (bits.size() > capacity) {
}
}
- // Get number of data bytes and number of error correction bytes for block id "blockID". Store
- // the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of
- // JISX0510:2004 (p.30)
+ /**
+ * Get number of data bytes and number of error correction bytes for block id "blockID". Store
+ * the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of
+ * JISX0510:2004 (p.30)
+ */
static void getNumDataBytesAndNumECBytesForBlockID(int numTotalBytes, int numDataBytes,
int numRSBlocks, int blockID, int[] numDataBytesInBlock,
int[] numECBytesInBlock) throws WriterException {
}
}
- // Interleave "bits" with corresponding error correction bytes. On success, store the result in
- // "result" and return true. The interleave rule is complicated. See 8.6
- // of JISX0510:2004 (p.37) for details.
+ /**
+ * Interleave "bits" with corresponding error correction bytes. On success, store the result in
+ * "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details.
+ */
static void interleaveWithECBytes(BitVector bits, int numTotalBytes,
int numDataBytes, int numRSBlocks, BitVector result) throws WriterException {
return ecBytes;
}
- // Append mode info. On success, store the result in "bits" and return true. On error, return
- // false.
+ /**
+ * Append mode info. On success, store the result in "bits".
+ */
static void appendModeInfo(Mode mode, BitVector bits) {
bits.appendBits(mode.getBits(), 4);
}
- // Append length info. On success, store the result in "bits" and return true. On error, return
- // false.
+ /**
+ * Append length info. On success, store the result in "bits".
+ */
static void appendLengthInfo(int numLetters, int version, Mode mode, BitVector bits) throws WriterException {
int numBits = mode.getCharacterCountBits(Version.getVersionForNumber(version));
if (numLetters > ((1 << numBits) - 1)) {
bits.appendBits(numLetters, numBits);
}
- // Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits"
- // and return true.
- static void appendBytes(String content, Mode mode, BitVector bits) throws WriterException {
+ /**
+ * Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits".
+ */
+ static void appendBytes(String content, Mode mode, BitVector bits, String encoding) throws WriterException {
if (mode.equals(Mode.NUMERIC)) {
appendNumericBytes(content, bits);
} else if (mode.equals(Mode.ALPHANUMERIC)) {
appendAlphanumericBytes(content, bits);
} else if (mode.equals(Mode.BYTE)) {
- append8BitBytes(content, bits);
+ append8BitBytes(content, bits, encoding);
} else if (mode.equals(Mode.KANJI)) {
appendKanjiBytes(content, bits);
} else {
}
}
- static void append8BitBytes(String content, BitVector bits) throws WriterException {
+ static void append8BitBytes(String content, BitVector bits, String encoding) throws WriterException {
byte[] bytes;
try {
- bytes = content.getBytes("ISO-8859-1"); // TODO support specifying encoding?
+ bytes = content.getBytes(encoding);
} catch (UnsupportedEncodingException uee) {
throw new WriterException(uee.toString());
}