Package net.sourceforge.jiu.codecs.tiff

Source Code of net.sourceforge.jiu.codecs.tiff.TIFFDecoderModifiedHuffman

/*
* TIFFDecoderModifiedHuffman
*
* Copyright (c) 2002, 2003, 2004, 2005, 2006 Marco Schmidt.
* All rights reserved.
*/

package net.sourceforge.jiu.codecs.tiff;

import java.io.DataInput;
import java.io.IOException;
import net.sourceforge.jiu.codecs.tiff.TIFFDecoder;
import net.sourceforge.jiu.codecs.InvalidFileStructureException;
import net.sourceforge.jiu.data.BilevelImage;
import net.sourceforge.jiu.ops.MissingParameterException;

/**
* A TIFF decoder for files compresseed with the <em>Modified Huffman</em> method
* (also known as <em>CCITT 1D Modified Huffman Run Length Encoding</em>).
* This compression algorithm has the value <code>2</code>
* in the compression tag of an image file directory.
* Only bilevel images can be encoded with that method.
* @author Marco Schmidt
* @since 0.9.0
*/
public class TIFFDecoderModifiedHuffman extends TIFFDecoder
{
  private DataInput in;
  private int bitBuffer;
  private int numBufferedBits;

  public void decode() throws
    InvalidFileStructureException,
    IOException
  {
    byte[] row = new byte[getBytesPerRow()];
    for (int y = getY1(); y <= getY2(); y++)
    {
      decodeRow(row);
      putBytes(row, 0, row.length);
    }
  }

  private int decodeBlackRun() throws
    InvalidFileStructureException,
    IOException
  {
    return decodeRun(TIFFFaxCodes.BLACK_CODES, TIFFFaxCodes.MIN_BLACK_CODE_SIZE);
  }

  private void decodeRow(byte[] row) throws
    InvalidFileStructureException,
    IOException
  {
    reset();
    boolean black = false;
    int index = 0;
    do
    {
      // this will hold the accumulated run length for the current
      // color at the end of this loop iteration
      int completeRunLength = 0;
      // get run lengths regarding current color until one is smaller than 64
      int runLength;
      do
      {
        if (black)
        {
          runLength = decodeBlackRun();
        }
        else
        {
          runLength = decodeWhiteRun();
        }
        completeRunLength += runLength;
      }
      while (runLength >= 64);
      // pick color value for output row
      byte value;
      if (black)
      {
        value = (byte)BilevelImage.BLACK;
      }
      else
      {
        value = (byte)BilevelImage.WHITE;
      }
      // fill row buffer with value
      while (completeRunLength-- > 0)
      {
        row[index++] = value;
      }
      // switch colors (black to white or vice versa)
      black = !black;
    }
    while (index < row.length);
  }

  private int decodeRun(int[][][] codes, int minCodeSize) throws
    InvalidFileStructureException,
    IOException
  {
    int code = readBits(minCodeSize);
    //int currentCodeSize = minCodeSize;
    for (int i = 0; i < codes.length; i++)
    {
      int[][] data = codes[i];
      int j = 0;
      final int LENGTH = data.length;
      while (j < LENGTH)
      {
        int[] pair = data[j++];
        if (pair[TIFFFaxCodes.INDEX_CODE_WORD] == code)
        {
          return pair[TIFFFaxCodes.INDEX_CODE_VALUE];
        }
      }
      code = (code << 1) | readBit();
    }
    throw new InvalidFileStructureException("Could not identify Huffman code in TIFF file.");
  }

  private int decodeWhiteRun() throws
    InvalidFileStructureException,
    IOException
  {
    return decodeRun(TIFFFaxCodes.WHITE_CODES, TIFFFaxCodes.MIN_WHITE_CODE_SIZE);
  }

  public Integer[] getCompressionTypes()
  {
    return new Integer[] {new Integer(TIFFConstants.COMPRESSION_CCITT_GROUP3_1D_MODIFIED_HUFFMAN)};
  }

  public void initialize() throws
    IOException,
    MissingParameterException
  {
    super.initialize();
    in = getInput();
  }

  private int readBit() throws IOException
  {
    int result;
    if (numBufferedBits == 0)
    {
      bitBuffer = in.readUnsignedByte();
      if ((bitBuffer & 0x80) == 0)
      {
        result = 0;
      }
      else
      {
        result = 1;
      }
      bitBuffer &= 0x7f;
      numBufferedBits = 7;
    }
    else
    {
      numBufferedBits--;
      result = bitBuffer >> numBufferedBits;
      bitBuffer &= (1 << numBufferedBits) - 1;
    }
    return result;
  }

  private int readBits(int number) throws IOException
  {
    // make sure there are at least number bits
    while (numBufferedBits < number)
    {
      int b = in.readUnsignedByte();
      bitBuffer = (bitBuffer << 8) | b;
      numBufferedBits += 8;
    }
    numBufferedBits -= number;
    int result = bitBuffer >> numBufferedBits;
    bitBuffer &= (1 << numBufferedBits) - 1;
    return result;
  }

  private void reset()
  {
    bitBuffer = 0;
    numBufferedBits = 0;
  }
}
TOP

Related Classes of net.sourceforge.jiu.codecs.tiff.TIFFDecoderModifiedHuffman

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.