private static void decodeByteSegment( BitSource bits, StringBuffer result, int count, CharacterSetECI currentCharacterSetECI, Vector byteSegments, Hashtable hints) throws FormatException { // Don't crash trying to read more bits than we have available. if (count << 3 > bits.available()) { throw FormatException.getFormatInstance(); } byte[] readBytes = new byte[count]; for (int i = 0; i < count; i++) { readBytes[i] = (byte) bits.readBits(8); } String encoding; if (currentCharacterSetECI == null) { // The spec isn't clear on this mode; see // section 6.4.5: t does not say which encoding to assuming // upon decoding. I have seen ISO-8859-1 used as well as // Shift_JIS -- without anything like an ECI designator to // give a hint. encoding = StringUtils.guessEncoding(readBytes, hints); } else { encoding = currentCharacterSetECI.getEncodingName(); } try { result.append(new String(readBytes, encoding)); } catch (UnsupportedEncodingException uce) { throw FormatException.getFormatInstance(); } byteSegments.addElement(readBytes); }
private static void a( BitSource paramBitSource, StringBuilder paramStringBuilder, int paramInt, CharacterSetECI paramCharacterSetECI, Collection<byte[]> paramCollection, Map<DecodeHintType, ?> paramMap) { if (paramInt << 3 > paramBitSource.available()) throw FormatException.getFormatInstance(); byte[] arrayOfByte = new byte[paramInt]; for (int i = 0; i < paramInt; i++) arrayOfByte[i] = ((byte) paramBitSource.readBits(8)); String str; if (paramCharacterSetECI == null) str = StringUtils.guessEncoding(arrayOfByte, paramMap); try { while (true) { paramStringBuilder.append(new String(arrayOfByte, str)); paramCollection.add(arrayOfByte); return; str = paramCharacterSetECI.name(); } } catch (UnsupportedEncodingException localUnsupportedEncodingException) { } throw FormatException.getFormatInstance(); }
/** * Performs high-level encoding of a PDF417 message using the algorithm described in annex P of * ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction is used. * * @param msg the message * @param compaction compaction mode to use * @param encoding character encoding used to encode in default or byte compaction or {@code null} * for default / not applicable * @return the encoded message (the char values range from 0 to 928) */ static String encodeHighLevel(String msg, Compaction compaction, Charset encoding) throws WriterException { // the codewords 0..928 are encoded as Unicode characters StringBuilder sb = new StringBuilder(msg.length()); if (encoding == null) { encoding = DEFAULT_ENCODING; } else if (!DEFAULT_ENCODING.equals(encoding)) { CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding.name()); if (eci != null) { encodingECI(eci.getValue(), sb); } } int len = msg.length(); int p = 0; int textSubMode = SUBMODE_ALPHA; // User selected encoding mode if (compaction == Compaction.TEXT) { encodeText(msg, p, len, sb, textSubMode); } else if (compaction == Compaction.BYTE) { byte[] bytes = msg.getBytes(encoding); encodeBinary(bytes, p, bytes.length, BYTE_COMPACTION, sb); } else if (compaction == Compaction.NUMERIC) { sb.append((char) LATCH_TO_NUMERIC); encodeNumeric(msg, p, len, sb); } else { int encodingMode = TEXT_COMPACTION; // Default mode, see 4.4.2.1 while (p < len) { int n = determineConsecutiveDigitCount(msg, p); if (n >= 13) { sb.append((char) LATCH_TO_NUMERIC); encodingMode = NUMERIC_COMPACTION; textSubMode = SUBMODE_ALPHA; // Reset after latch encodeNumeric(msg, p, n, sb); p += n; } else { int t = determineConsecutiveTextCount(msg, p); if (t >= 5 || n == len) { if (encodingMode != TEXT_COMPACTION) { sb.append((char) LATCH_TO_TEXT); encodingMode = TEXT_COMPACTION; textSubMode = SUBMODE_ALPHA; // start with submode alpha after latch } textSubMode = encodeText(msg, p, t, sb, textSubMode); p += t; } else { int b = determineConsecutiveBinaryCount(msg, p, encoding); if (b == 0) { b = 1; } byte[] bytes = msg.substring(p, p + b).getBytes(encoding); if (bytes.length == 1 && encodingMode == TEXT_COMPACTION) { // Switch for one byte (instead of latch) encodeBinary(bytes, 0, 1, TEXT_COMPACTION, sb); } else { // Mode latch performed by encodeBinary() encodeBinary(bytes, 0, bytes.length, encodingMode, sb); encodingMode = BYTE_COMPACTION; textSubMode = SUBMODE_ALPHA; // Reset after latch } p += b; } } } } return sb.toString(); }
static DecoderResult decode( byte[] bytes, Version version, ErrorCorrectionLevel ecLevel, Hashtable hints) throws FormatException { BitSource bits = new BitSource(bytes); StringBuffer result = new StringBuffer(50); CharacterSetECI currentCharacterSetECI = null; boolean fc1InEffect = false; Vector byteSegments = new Vector(1); Mode mode; do { // While still another segment to read... if (bits.available() < 4) { // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here mode = Mode.TERMINATOR; } else { try { mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits } catch (IllegalArgumentException iae) { throw FormatException.getFormatInstance(); } } if (!mode.equals(Mode.TERMINATOR)) { if (mode.equals(Mode.FNC1_FIRST_POSITION) || mode.equals(Mode.FNC1_SECOND_POSITION)) { // We do little with FNC1 except alter the parsed result a bit according to the spec fc1InEffect = true; } else if (mode.equals(Mode.STRUCTURED_APPEND)) { // not really supported; all we do is ignore it // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue bits.readBits(16); } else if (mode.equals(Mode.ECI)) { // Count doesn't apply to ECI int value = parseECIValue(bits); currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value); if (currentCharacterSetECI == null) { throw FormatException.getFormatInstance(); } } else { // First handle Hanzi mode which does not start with character count if (mode.equals(Mode.HANZI)) { // chinese mode contains a sub set indicator right after mode indicator int subset = bits.readBits(4); int countHanzi = bits.readBits(mode.getCharacterCountBits(version)); if (subset == GB2312_SUBSET) { decodeHanziSegment(bits, result, countHanzi); } } else { // "Normal" QR code modes: // How many characters will follow, encoded in this mode? int count = bits.readBits(mode.getCharacterCountBits(version)); if (mode.equals(Mode.NUMERIC)) { decodeNumericSegment(bits, result, count); } else if (mode.equals(Mode.ALPHANUMERIC)) { decodeAlphanumericSegment(bits, result, count, fc1InEffect); } else if (mode.equals(Mode.BYTE)) { decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints); } else if (mode.equals(Mode.KANJI)) { decodeKanjiSegment(bits, result, count); } else { throw FormatException.getFormatInstance(); } } } } } while (!mode.equals(Mode.TERMINATOR)); return new DecoderResult( bytes, result.toString(), byteSegments.isEmpty() ? null : byteSegments, ecLevel == null ? null : ecLevel.toString()); }
static DecoderResult a( byte[] paramArrayOfByte, Version paramVersion, ErrorCorrectionLevel paramErrorCorrectionLevel, Map<DecodeHintType, ?> paramMap) { BitSource localBitSource = new BitSource(paramArrayOfByte); StringBuilder localStringBuilder = new StringBuilder(50); CharacterSetECI localCharacterSetECI = null; boolean bool1 = false; ArrayList localArrayList = new ArrayList(1); while (true) { Object localObject; boolean bool2; if (localBitSource.available() < 4) { localObject = Mode.TERMINATOR; if (localObject == Mode.TERMINATOR) break label502; if ((localObject != Mode.FNC1_FIRST_POSITION) && (localObject != Mode.FNC1_SECOND_POSITION)) break label152; bool2 = true; } while (true) { label78: if (localObject != Mode.TERMINATOR) break label509; String str1 = localStringBuilder.toString(); if (localArrayList.isEmpty()) localArrayList = null; if (paramErrorCorrectionLevel == null) ; for (String str2 = null; ; str2 = paramErrorCorrectionLevel.toString()) { while (true) { return new DecoderResult(paramArrayOfByte, str1, localArrayList, str2); try { Mode localMode = Mode.forBits(localBitSource.readBits(4)); localObject = localMode; } catch (IllegalArgumentException localIllegalArgumentException) { throw FormatException.getFormatInstance(); } } label152: if (localObject == Mode.STRUCTURED_APPEND) { localBitSource.readBits(16); bool2 = bool1; break label78; } if (localObject == Mode.ECI) { int m = localBitSource.readBits(8); int n; if ((m & 0x80) == 0) n = m & 0x7F; while (true) { localCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(n); if (localCharacterSetECI != null) break label315; throw FormatException.getFormatInstance(); if ((m & 0xC0) == 128) { n = localBitSource.readBits(8) | (m & 0x3F) << 8; } else { if ((m & 0xE0) != 192) break; n = localBitSource.readBits(16) | (m & 0x1F) << 16; } } throw new IllegalArgumentException("Bad ECI bits starting with byte " + m); label315: bool2 = bool1; break label78; } if (localObject == Mode.HANZI) { int j = localBitSource.readBits(4); int k = localBitSource.readBits(((Mode) localObject).getCharacterCountBits(paramVersion)); if (j == 1) a(localBitSource, localStringBuilder, k); bool2 = bool1; break label78; } int i = localBitSource.readBits(((Mode) localObject).getCharacterCountBits(paramVersion)); if (localObject == Mode.NUMERIC) { c(localBitSource, localStringBuilder, i); bool2 = bool1; break label78; } if (localObject == Mode.ALPHANUMERIC) { a(localBitSource, localStringBuilder, i, bool1); bool2 = bool1; break label78; } if (localObject == Mode.BYTE) { a( localBitSource, localStringBuilder, i, localCharacterSetECI, localArrayList, paramMap); bool2 = bool1; break label78; } if (localObject == Mode.KANJI) { b(localBitSource, localStringBuilder, i); bool2 = bool1; break label78; } throw FormatException.getFormatInstance(); } label502: bool2 = bool1; } label509: bool1 = bool2; } }
private static void a(CharacterSetECI characterseteci, BitArray bitarray) { bitarray.appendBits(Mode.ECI.getBits(), 4); bitarray.appendBits(characterseteci.getValue(), 8); }