Exemplo n.º 1
0
  private PngHuffmanTables(PngDecodingDataStream stream) throws IOException {
    int literals = PngLzBlockReader.FIRST_LENGTH_CODE + stream.getNextIdatBits(5);
    int distances = PngLzBlockReader.FIRST_DISTANCE_CODE + stream.getNextIdatBits(5);
    int codeLengthCodes = PngLzBlockReader.FIRST_CODE_LENGTH_CODE + stream.getNextIdatBits(4);

    if (codeLengthCodes > PngLzBlockReader.LAST_CODE_LENGTH_CODE) {
      stream.error();
    }

    /* Tricky, tricky, tricky. The length codes are stored in
     * a very odd order. (For the order, see the definition of
     * the static field lengthCodeOrder.) Also, the data may
     * not contain values for all the codes. It may just contain
     * values for the first X number of codes. The table should
     * be of size <LengthCodeTableSize> regardless of the number
     * of values actually given in the table.
     */
    int[] lengthCodes = new int[LengthCodeTableSize];
    for (int i = 0; i < codeLengthCodes; i++) {
      lengthCodes[LengthCodeOrder[i]] = stream.getNextIdatBits(3);
    }
    PngHuffmanTable codeLengthsTable = new PngHuffmanTable(lengthCodes);

    int[] literalLengths = readLengths(stream, literals, codeLengthsTable, LiteralTableSize);
    int[] distanceLengths = readLengths(stream, distances, codeLengthsTable, DistanceTableSize);

    literalTable = new PngHuffmanTable(literalLengths);
    distanceTable = new PngHuffmanTable(distanceLengths);
  }
Exemplo n.º 2
0
  private int[] readLengths(
      PngDecodingDataStream stream, int numLengths, PngHuffmanTable lengthsTable, int tableSize)
      throws IOException {
    int[] lengths = new int[tableSize];

    for (int index = 0; index < numLengths; ) {
      int value = lengthsTable.getNextValue(stream);
      if (value < 16) {
        // Literal value
        lengths[index] = value;
        index++;
      } else if (value == 16) {
        // Repeat the previous code 3-6 times.
        int count = stream.getNextIdatBits(2) + 3;
        for (int i = 0; i < count; i++) {
          lengths[index] = lengths[index - 1];
          index++;
        }
      } else if (value == 17) {
        // Repeat 0 3-10 times.
        int count = stream.getNextIdatBits(3) + 3;
        for (int i = 0; i < count; i++) {
          lengths[index] = 0;
          index++;
        }
      } else if (value == 18) {
        // Repeat 0 11-138 times.
        int count = stream.getNextIdatBits(7) + 11;
        for (int i = 0; i < count; i++) {
          lengths[index] = 0;
          index++;
        }
      } else {
        stream.error();
      }
    }
    return lengths;
  }
  int getNextValue(PngDecodingDataStream stream) throws IOException {
    int code = stream.getNextIdatBit();
    int codelength = 0;

    // Here we are taking advantage of the fact that 1 bits are used as
    // a prefix to the longer codeValues.
    while (codelength < MAX_CODE_LENGTH && code > codeLengthInfo[codelength].max) {
      code = ((code << 1) | stream.getNextIdatBit());
      codelength++;
    }
    if (codelength >= MAX_CODE_LENGTH) stream.error();

    // Now we have a Huffman code of length (codelength + 1) that
    // is somewhere in the range
    // minCodesByLength[codelength]..maxCodesByLength[codelength].
    // This code is the (offset + 1)'th code of (codelength + 1);
    int offset = code - codeLengthInfo[codelength].min;

    // indexesByLength[codelength] is the first code of length (codelength + 1)
    // so now we can look up the value for the Huffman code in the table.
    int index = codeLengthInfo[codelength].baseIndex + offset;
    return codeValues[index];
  }