Java Code Examples for com.google.zxing.common.BitSource#readBits()

The following examples show how to use com.google.zxing.common.BitSource#readBits() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DecodedBitStreamParser.java    From ZXing-Orient with Apache License 2.0 6 votes vote down vote up
private static int parseECIValue(BitSource bits) throws FormatException {
  int firstByte = bits.readBits(8);
  if ((firstByte & 0x80) == 0) {
    // just one byte
    return firstByte & 0x7F;
  }
  if ((firstByte & 0xC0) == 0x80) {
    // two bytes
    int secondByte = bits.readBits(8);
    return ((firstByte & 0x3F) << 8) | secondByte;
  }
  if ((firstByte & 0xE0) == 0xC0) {
    // three bytes
    int secondThirdBytes = bits.readBits(16);
    return ((firstByte & 0x1F) << 16) | secondThirdBytes;
  }
  throw FormatException.getFormatInstance();
}
 
Example 2
Source File: DecodedBitStreamParser.java    From analyzer-of-android-for-Apache-Weex with Apache License 2.0 5 votes vote down vote up
private static void decodeByteSegment(BitSource bits,
                                      StringBuilder result,
                                      int count,
                                      CharacterSetECI currentCharacterSetECI,
                                      Collection<byte[]> byteSegments,
                                      Map<DecodeHintType,?> hints) throws FormatException {
  // Don't crash trying to read more bits than we have available.
  if (8 * count > 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.name();
  }
  try {
    result.append(new String(readBytes, encoding));
  } catch (UnsupportedEncodingException ignored) {
    throw FormatException.getFormatInstance();
  }
  byteSegments.add(readBytes);
}
 
Example 3
Source File: DecodedBitStreamParser.java    From reacteu-app with MIT License 5 votes vote down vote up
private static void decodeByteSegment(BitSource bits,
                                      StringBuilder result,
                                      int count,
                                      CharacterSetECI currentCharacterSetECI,
                                      Collection<byte[]> byteSegments,
                                      Map<DecodeHintType,?> 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.name();
  }
  try {
    result.append(new String(readBytes, encoding));
  } catch (UnsupportedEncodingException uce) {
    throw FormatException.getFormatInstance();
  }
  byteSegments.add(readBytes);
}
 
Example 4
Source File: DecodedBitStreamParser.java    From barterli_android with Apache License 2.0 5 votes vote down vote up
/**
 * See specification GBT 18284-2000
 */
private static void decodeHanziSegment(BitSource bits, StringBuilder result, int count) throws FormatException {
    // Don't crash trying to read more bits than we have available.
    if (count * 13 > bits.available()) {
        throw FormatException.getFormatInstance();
    }

    // Each character will require 2 bytes. Read the characters as 2-byte
    // pairs
    // and decode as GB2312 afterwards
    byte[] buffer = new byte[2 * count];
    int offset = 0;
    while (count > 0) {
        // Each 13 bits encodes a 2-byte character
        int twoBytes = bits.readBits(13);
        int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);
        if (assembledTwoBytes < 0x003BF) {
            // In the 0xA1A1 to 0xAAFE range
            assembledTwoBytes += 0x0A1A1;
        } else {
            // In the 0xB0A1 to 0xFAFE range
            assembledTwoBytes += 0x0A6A1;
        }
        buffer[offset] = (byte) ((assembledTwoBytes >> 8) & 0xFF);
        buffer[offset + 1] = (byte) (assembledTwoBytes & 0xFF);
        offset += 2;
        count--;
    }

    try {
        result.append(new String(buffer, StringUtils.GB2312));
    } catch (UnsupportedEncodingException uee) {
        throw FormatException.getFormatInstance();
    }
}
 
Example 5
Source File: DecodedBitStreamParser.java    From barcodescanner-lib-aar with MIT License 5 votes vote down vote up
/**
 * See ISO 16022:2006, 5.2.8 and Annex C Table C.3
 */
private static void decodeEdifactSegment(BitSource bits, StringBuilder result) {
  do {
    // If there is only two or less bytes left then it will be encoded as ASCII
    if (bits.available() <= 16) {
      return;
    }

    for (int i = 0; i < 4; i++) {
      int edifactValue = bits.readBits(6);

      // Check for the unlatch character
      if (edifactValue == 0x1F) {  // 011111
        // Read rest of byte, which should be 0, and stop
        int bitsLeft = 8 - bits.getBitOffset();
        if (bitsLeft != 8) {
          bits.readBits(bitsLeft);
        }
        return;
      }

      if ((edifactValue & 0x20) == 0) {  // no 1 in the leading (6th) bit
        edifactValue |= 0x40;  // Add a leading 01 to the 6 bit binary value
      }
      result.append((char) edifactValue);
    }
  } while (bits.available() > 0);
}
 
Example 6
Source File: DecodedBitStreamParser.java    From QrCodeScanner with GNU General Public License v3.0 5 votes vote down vote up
/**
 * See specification GBT 18284-2000
 */
private static void decodeHanziSegment(BitSource bits,
                                       StringBuilder result,
                                       int count) throws FormatException {
  // Don't crash trying to read more bits than we have available.
  if (count * 13 > bits.available()) {
    throw FormatException.getFormatInstance();
  }

  // Each character will require 2 bytes. Read the characters as 2-byte pairs
  // and decode as GB2312 afterwards
  byte[] buffer = new byte[2 * count];
  int offset = 0;
  while (count > 0) {
    // Each 13 bits encodes a 2-byte character
    int twoBytes = bits.readBits(13);
    int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);
    if (assembledTwoBytes < 0x003BF) {
      // In the 0xA1A1 to 0xAAFE range
      assembledTwoBytes += 0x0A1A1;
    } else {
      // In the 0xB0A1 to 0xFAFE range
      assembledTwoBytes += 0x0A6A1;
    }
    buffer[offset] = (byte) ((assembledTwoBytes >> 8) & 0xFF);
    buffer[offset + 1] = (byte) (assembledTwoBytes & 0xFF);
    offset += 2;
    count--;
  }

  try {
    result.append(new String(buffer, StringUtils.GB2312));
  } catch (UnsupportedEncodingException ignored) {
    throw FormatException.getFormatInstance();
  }
}
 
Example 7
Source File: DecodedBitStreamParser.java    From barterli_android with Apache License 2.0 5 votes vote down vote up
private static void decodeByteSegment(BitSource bits, StringBuilder result, int count, CharacterSetECI currentCharacterSetECI,
        Collection<byte[]> byteSegments, Map<DecodeHintType, ?> 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.name();
    }
    try {
        result.append(new String(readBytes, encoding));
    } catch (UnsupportedEncodingException uce) {
        throw FormatException.getFormatInstance();
    }
    byteSegments.add(readBytes);
}
 
Example 8
Source File: DecodedBitStreamParser.java    From reacteu-app with MIT License 5 votes vote down vote up
private static void decodeKanjiSegment(BitSource bits,
                                       StringBuilder result,
                                       int count) throws FormatException {
  // Don't crash trying to read more bits than we have available.
  if (count * 13 > bits.available()) {
    throw FormatException.getFormatInstance();
  }

  // Each character will require 2 bytes. Read the characters as 2-byte pairs
  // and decode as Shift_JIS afterwards
  byte[] buffer = new byte[2 * count];
  int offset = 0;
  while (count > 0) {
    // Each 13 bits encodes a 2-byte character
    int twoBytes = bits.readBits(13);
    int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0);
    if (assembledTwoBytes < 0x01F00) {
      // In the 0x8140 to 0x9FFC range
      assembledTwoBytes += 0x08140;
    } else {
      // In the 0xE040 to 0xEBBF range
      assembledTwoBytes += 0x0C140;
    }
    buffer[offset] = (byte) (assembledTwoBytes >> 8);
    buffer[offset + 1] = (byte) assembledTwoBytes;
    offset += 2;
    count--;
  }
  // Shift_JIS may not be supported in some environments:
  try {
    result.append(new String(buffer, StringUtils.SHIFT_JIS));
  } catch (UnsupportedEncodingException uee) {
    throw FormatException.getFormatInstance();
  }
}
 
Example 9
Source File: DecodedBitStreamParser.java    From weex with Apache License 2.0 5 votes vote down vote up
private static void decodeByteSegment(BitSource bits,
                                      StringBuilder result,
                                      int count,
                                      CharacterSetECI currentCharacterSetECI,
                                      Collection<byte[]> byteSegments,
                                      Map<DecodeHintType,?> hints) throws FormatException {
  // Don't crash trying to read more bits than we have available.
  if (8 * count > 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.name();
  }
  try {
    result.append(new String(readBytes, encoding));
  } catch (UnsupportedEncodingException ignored) {
    throw FormatException.getFormatInstance();
  }
  byteSegments.add(readBytes);
}
 
Example 10
Source File: DecodedBitStreamParser.java    From RipplePower with Apache License 2.0 5 votes vote down vote up
/**
 * See specification GBT 18284-2000
 */
private static void decodeHanziSegment(BitSource bits, StringBuilder result, int count) throws FormatException {
	// Don't crash trying to read more bits than we have available.
	if (count * 13 > bits.available()) {
		throw FormatException.getFormatInstance();
	}

	// Each character will require 2 bytes. Read the characters as 2-byte
	// pairs
	// and decode as GB2312 afterwards
	byte[] buffer = new byte[2 * count];
	int offset = 0;
	while (count > 0) {
		// Each 13 bits encodes a 2-byte character
		int twoBytes = bits.readBits(13);
		int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);
		if (assembledTwoBytes < 0x003BF) {
			// In the 0xA1A1 to 0xAAFE range
			assembledTwoBytes += 0x0A1A1;
		} else {
			// In the 0xB0A1 to 0xFAFE range
			assembledTwoBytes += 0x0A6A1;
		}
		buffer[offset] = (byte) ((assembledTwoBytes >> 8) & 0xFF);
		buffer[offset + 1] = (byte) (assembledTwoBytes & 0xFF);
		offset += 2;
		count--;
	}

	try {
		result.append(new String(buffer, StringUtils.GB2312));
	} catch (UnsupportedEncodingException ignored) {
		throw FormatException.getFormatInstance();
	}
}
 
Example 11
Source File: DecodedBitStreamParser.java    From RipplePower with Apache License 2.0 5 votes vote down vote up
private static void decodeAlphanumericSegment(BitSource bits, StringBuilder result, int count, boolean fc1InEffect)
		throws FormatException {
	// Read two characters at a time
	int start = result.length();
	while (count > 1) {
		if (bits.available() < 11) {
			throw FormatException.getFormatInstance();
		}
		int nextTwoCharsBits = bits.readBits(11);
		result.append(toAlphaNumericChar(nextTwoCharsBits / 45));
		result.append(toAlphaNumericChar(nextTwoCharsBits % 45));
		count -= 2;
	}
	if (count == 1) {
		// special case: one character left
		if (bits.available() < 6) {
			throw FormatException.getFormatInstance();
		}
		result.append(toAlphaNumericChar(bits.readBits(6)));
	}
	// See section 6.4.8.1, 6.4.8.2
	if (fc1InEffect) {
		// We need to massage the result a bit if in an FNC1 mode:
		for (int i = start; i < result.length(); i++) {
			if (result.charAt(i) == '%') {
				if (i < result.length() - 1 && result.charAt(i + 1) == '%') {
					// %% is rendered as %
					result.deleteCharAt(i + 1);
				} else {
					// In alpha mode, % should be converted to FNC1
					// separator 0x1D
					result.setCharAt(i, (char) 0x1D);
				}
			}
		}
	}
}
 
Example 12
Source File: DecodedBitStreamParser.java    From ScreenCapture with MIT License 5 votes vote down vote up
private static void decodeAlphanumericSegment(BitSource bits,
                                              StringBuilder result,
                                              int count,
                                              boolean fc1InEffect) throws FormatException {
  // Read two characters at a time
  int start = result.length();
  while (count > 1) {
    if (bits.available() < 11) {
      throw FormatException.getFormatInstance();
    }
    int nextTwoCharsBits = bits.readBits(11);
    result.append(toAlphaNumericChar(nextTwoCharsBits / 45));
    result.append(toAlphaNumericChar(nextTwoCharsBits % 45));
    count -= 2;
  }
  if (count == 1) {
    // special case: one character left
    if (bits.available() < 6) {
      throw FormatException.getFormatInstance();
    }
    result.append(toAlphaNumericChar(bits.readBits(6)));
  }
  // See section 6.4.8.1, 6.4.8.2
  if (fc1InEffect) {
    // We need to massage the result a bit if in an FNC1 mode:
    for (int i = start; i < result.length(); i++) {
      if (result.charAt(i) == '%') {
        if (i < result.length() - 1 && result.charAt(i + 1) == '%') {
          // %% is rendered as %
          result.deleteCharAt(i + 1);
        } else {
          // In alpha mode, % should be converted to FNC1 separator 0x1D
          result.setCharAt(i, (char) 0x1D);
        }
      }
    }
  }
}
 
Example 13
Source File: DecodedBitStreamParser.java    From ScreenCapture with MIT License 5 votes vote down vote up
private static void decodeByteSegment(BitSource bits,
                                      StringBuilder result,
                                      int count,
                                      CharacterSetECI currentCharacterSetECI,
                                      Collection<byte[]> byteSegments,
                                      Map<DecodeHintType,?> hints) throws FormatException {
  // Don't crash trying to read more bits than we have available.
  if (8 * count > 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.name();
  }
  try {
    result.append(new String(readBytes, encoding));
  } catch (UnsupportedEncodingException ignored) {
    throw FormatException.getFormatInstance();
  }
  byteSegments.add(readBytes);
}
 
Example 14
Source File: DecodedBitStreamParser.java    From barcodescanner-lib-aar with MIT License 5 votes vote down vote up
private static void decodeAlphanumericSegment(BitSource bits,
                                              StringBuilder result,
                                              int count,
                                              boolean fc1InEffect) throws FormatException {
  // Read two characters at a time
  int start = result.length();
  while (count > 1) {
    if (bits.available() < 11) {
      throw FormatException.getFormatInstance();
    }
    int nextTwoCharsBits = bits.readBits(11);
    result.append(toAlphaNumericChar(nextTwoCharsBits / 45));
    result.append(toAlphaNumericChar(nextTwoCharsBits % 45));
    count -= 2;
  }
  if (count == 1) {
    // special case: one character left
    if (bits.available() < 6) {
      throw FormatException.getFormatInstance();
    }
    result.append(toAlphaNumericChar(bits.readBits(6)));
  }
  // See section 6.4.8.1, 6.4.8.2
  if (fc1InEffect) {
    // We need to massage the result a bit if in an FNC1 mode:
    for (int i = start; i < result.length(); i++) {
      if (result.charAt(i) == '%') {
        if (i < result.length() - 1 && result.charAt(i + 1) == '%') {
          // %% is rendered as %
          result.deleteCharAt(i + 1);
        } else {
          // In alpha mode, % should be converted to FNC1 separator 0x1D
          result.setCharAt(i, (char) 0x1D);
        }
      }
    }
  }
}
 
Example 15
Source File: DecodedBitStreamParser.java    From reacteu-app with MIT License 5 votes vote down vote up
/**
 * See specification GBT 18284-2000
 */
private static void decodeHanziSegment(BitSource bits,
                                       StringBuilder result,
                                       int count) throws FormatException {
  // Don't crash trying to read more bits than we have available.
  if (count * 13 > bits.available()) {
    throw FormatException.getFormatInstance();
  }

  // Each character will require 2 bytes. Read the characters as 2-byte pairs
  // and decode as GB2312 afterwards
  byte[] buffer = new byte[2 * count];
  int offset = 0;
  while (count > 0) {
    // Each 13 bits encodes a 2-byte character
    int twoBytes = bits.readBits(13);
    int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);
    if (assembledTwoBytes < 0x003BF) {
      // In the 0xA1A1 to 0xAAFE range
      assembledTwoBytes += 0x0A1A1;
    } else {
      // In the 0xB0A1 to 0xFAFE range
      assembledTwoBytes += 0x0A6A1;
    }
    buffer[offset] = (byte) ((assembledTwoBytes >> 8) & 0xFF);
    buffer[offset + 1] = (byte) (assembledTwoBytes & 0xFF);
    offset += 2;
    count--;
  }

  try {
    result.append(new String(buffer, StringUtils.GB2312));
  } catch (UnsupportedEncodingException uee) {
    throw FormatException.getFormatInstance();
  }
}
 
Example 16
Source File: DecodedBitStreamParser.java    From ZXing-Orient with Apache License 2.0 4 votes vote down vote up
private static void decodeNumericSegment(BitSource bits,
                                         StringBuilder result,
                                         int count) throws FormatException {
  // Read three digits at a time
  while (count >= 3) {
    // Each 10 bits encodes three digits
    if (bits.available() < 10) {
      throw FormatException.getFormatInstance();
    }
    int threeDigitsBits = bits.readBits(10);
    if (threeDigitsBits >= 1000) {
      throw FormatException.getFormatInstance();
    }
    result.append(toAlphaNumericChar(threeDigitsBits / 100));
    result.append(toAlphaNumericChar((threeDigitsBits / 10) % 10));
    result.append(toAlphaNumericChar(threeDigitsBits % 10));
    count -= 3;
  }
  if (count == 2) {
    // Two digits left over to read, encoded in 7 bits
    if (bits.available() < 7) {
      throw FormatException.getFormatInstance();
    }
    int twoDigitsBits = bits.readBits(7);
    if (twoDigitsBits >= 100) {
      throw FormatException.getFormatInstance();
    }
    result.append(toAlphaNumericChar(twoDigitsBits / 10));
    result.append(toAlphaNumericChar(twoDigitsBits % 10));
  } else if (count == 1) {
    // One digit left over to read
    if (bits.available() < 4) {
      throw FormatException.getFormatInstance();
    }
    int digitBits = bits.readBits(4);
    if (digitBits >= 10) {
      throw FormatException.getFormatInstance();
    }
    result.append(toAlphaNumericChar(digitBits));
  }
}
 
Example 17
Source File: DecodedBitStreamParser.java    From Tesseract-OCR-Scanner with Apache License 2.0 4 votes vote down vote up
private static void decodeNumericSegment(BitSource bits,
                                         StringBuilder result,
                                         int count) throws FormatException {
  // Read three digits at a time
  while (count >= 3) {
    // Each 10 bits encodes three digits
    if (bits.available() < 10) {
      throw FormatException.getFormatInstance();
    }
    int threeDigitsBits = bits.readBits(10);
    if (threeDigitsBits >= 1000) {
      throw FormatException.getFormatInstance();
    }
    result.append(toAlphaNumericChar(threeDigitsBits / 100));
    result.append(toAlphaNumericChar((threeDigitsBits / 10) % 10));
    result.append(toAlphaNumericChar(threeDigitsBits % 10));
    count -= 3;
  }
  if (count == 2) {
    // Two digits left over to read, encoded in 7 bits
    if (bits.available() < 7) {
      throw FormatException.getFormatInstance();
    }
    int twoDigitsBits = bits.readBits(7);
    if (twoDigitsBits >= 100) {
      throw FormatException.getFormatInstance();
    }
    result.append(toAlphaNumericChar(twoDigitsBits / 10));
    result.append(toAlphaNumericChar(twoDigitsBits % 10));
  } else if (count == 1) {
    // One digit left over to read
    if (bits.available() < 4) {
      throw FormatException.getFormatInstance();
    }
    int digitBits = bits.readBits(4);
    if (digitBits >= 10) {
      throw FormatException.getFormatInstance();
    }
    result.append(toAlphaNumericChar(digitBits));
  }
}
 
Example 18
Source File: DecodedBitStreamParser.java    From android-quick-response-code with Apache License 2.0 4 votes vote down vote up
static DecoderResult decode(byte[] bytes, Version version, ErrorCorrectionLevel ecLevel, Map<DecodeHintType, ?> hints) throws FormatException {
    BitSource bits = new BitSource(bytes);
    StringBuilder result = new StringBuilder(50);
    CharacterSetECI currentCharacterSetECI = null;
    boolean fc1InEffect = false;
    List<byte[]> byteSegments = new ArrayList<byte[]>(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 != Mode.TERMINATOR) {
            if (mode == Mode.FNC1_FIRST_POSITION || mode == 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 == 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 == 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 == 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 == Mode.NUMERIC) {
                        decodeNumericSegment(bits, result, count);
                    } else if (mode == Mode.ALPHANUMERIC) {
                        decodeAlphanumericSegment(bits, result, count, fc1InEffect);
                    } else if (mode == Mode.BYTE) {
                        decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);
                    } else if (mode == Mode.KANJI) {
                        decodeKanjiSegment(bits, result, count);
                    } else {
                        throw FormatException.getFormatInstance();
                    }
                }
            }
        }
    } while (mode != Mode.TERMINATOR);

    return new DecoderResult(bytes, result.toString(), byteSegments.isEmpty() ? null : byteSegments, ecLevel == null ? null : ecLevel.toString());
}
 
Example 19
Source File: DecodedBitStreamParser.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
static DecoderResult decode(byte[] bytes,
                            Version version,
                            ErrorCorrectionLevel ecLevel,
                            Map<DecodeHintType,?> hints) throws FormatException {
  BitSource bits = new BitSource(bytes);
  StringBuilder result = new StringBuilder(50);
  List<byte[]> byteSegments = new ArrayList<>(1);
  int symbolSequence = -1;
  int parityData = -1;

  try {
    CharacterSetECI currentCharacterSetECI = null;
    boolean fc1InEffect = false;
    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 {
        mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
      }
      switch (mode) {
        case TERMINATOR:
          break;
        case FNC1_FIRST_POSITION:
        case FNC1_SECOND_POSITION:
          // We do little with FNC1 except alter the parsed result a bit according to the spec
          fc1InEffect = true;
          break;
        case STRUCTURED_APPEND:
          if (bits.available() < 16) {
            throw FormatException.getFormatInstance();
          }
          // sequence number and parity is added later to the result metadata
          // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
          symbolSequence = bits.readBits(8);
          parityData = bits.readBits(8);
          break;
        case ECI:
          // Count doesn't apply to ECI
          int value = parseECIValue(bits);
          currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);
          if (currentCharacterSetECI == null) {
            throw FormatException.getFormatInstance();
          }
          break;
        case HANZI:
          // First handle Hanzi mode which does not start with character count
          // 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);
          }
          break;
        default:
          // "Normal" QR code modes:
          // How many characters will follow, encoded in this mode?
          int count = bits.readBits(mode.getCharacterCountBits(version));
          switch (mode) {
            case NUMERIC:
              decodeNumericSegment(bits, result, count);
              break;
            case ALPHANUMERIC:
              decodeAlphanumericSegment(bits, result, count, fc1InEffect);
              break;
            case BYTE:
              decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);
              break;
            case KANJI:
              decodeKanjiSegment(bits, result, count);
              break;
            default:
              throw FormatException.getFormatInstance();
          }
          break;
      }
    } while (mode != Mode.TERMINATOR);
  } catch (IllegalArgumentException iae) {
    // from readBits() calls
    throw FormatException.getFormatInstance();
  }

  return new DecoderResult(bytes,
                           result.toString(),
                           byteSegments.isEmpty() ? null : byteSegments,
                           ecLevel == null ? null : ecLevel.toString(),
                           symbolSequence,
                           parityData);
}
 
Example 20
Source File: DecodedBitStreamParser.java    From ZXing-Orient with Apache License 2.0 4 votes vote down vote up
/**
 * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2
 */
private static Mode decodeAsciiSegment(BitSource bits,
                                       StringBuilder result,
                                       StringBuilder resultTrailer) throws FormatException {
  boolean upperShift = false;
  do {
    int oneByte = bits.readBits(8);
    if (oneByte == 0) {
      throw FormatException.getFormatInstance();
    } else if (oneByte <= 128) {  // ASCII data (ASCII value + 1)
      if (upperShift) {
        oneByte += 128;
        //upperShift = false;
      }
      result.append((char) (oneByte - 1));
      return Mode.ASCII_ENCODE;
    } else if (oneByte == 129) {  // Pad
      return Mode.PAD_ENCODE;
    } else if (oneByte <= 229) {  // 2-digit data 00-99 (Numeric Value + 130)
      int value = oneByte - 130;
      if (value < 10) { // padd with '0' for single digit values
        result.append('0');
      }
      result.append(value);
    } else if (oneByte == 230) {  // Latch to C40 encodation
      return Mode.C40_ENCODE;
    } else if (oneByte == 231) {  // Latch to Base 256 encodation
      return Mode.BASE256_ENCODE;
    } else if (oneByte == 232) {
      // FNC1
      result.append((char) 29); // translate as ASCII 29
    } else if (oneByte == 233 || oneByte == 234) {
      // Structured Append, Reader Programming
      // Ignore these symbols for now
      //throw ReaderException.getInstance();
    } else if (oneByte == 235) {  // Upper Shift (shift to Extended ASCII)
      upperShift = true;
    } else if (oneByte == 236) {  // 05 Macro
      result.append("[)>\u001E05\u001D");
      resultTrailer.insert(0, "\u001E\u0004");
    } else if (oneByte == 237) {  // 06 Macro
      result.append("[)>\u001E06\u001D");
      resultTrailer.insert(0, "\u001E\u0004");
    } else if (oneByte == 238) {  // Latch to ANSI X12 encodation
      return Mode.ANSIX12_ENCODE;
    } else if (oneByte == 239) {  // Latch to Text encodation
      return Mode.TEXT_ENCODE;
    } else if (oneByte == 240) {  // Latch to EDIFACT encodation
      return Mode.EDIFACT_ENCODE;
    } else if (oneByte == 241) {  // ECI Character
      // TODO(bbrown): I think we need to support ECI
      //throw ReaderException.getInstance();
      // Ignore this symbol for now
    } else if (oneByte >= 242) {  // Not to be used in ASCII encodation
      // ... but work around encoders that end with 254, latch back to ASCII
      if (oneByte != 254 || bits.available() != 0) {
        throw FormatException.getFormatInstance();
      }
    }
  } while (bits.available() > 0);
  return Mode.ASCII_ENCODE;
}