2009-09-30 23:50:03 +00:00
|
|
|
|
/*
|
|
|
|
|
|
* CVS identifier:
|
|
|
|
|
|
*
|
|
|
|
|
|
* $Id: BitOutputBuffer.java,v 1.9 2002/07/19 12:40:05 grosbois Exp $
|
|
|
|
|
|
*
|
|
|
|
|
|
* Class: BitOutputBuffer
|
|
|
|
|
|
*
|
|
|
|
|
|
* Description: <short description of class>
|
|
|
|
|
|
*
|
|
|
|
|
|
*
|
|
|
|
|
|
*
|
|
|
|
|
|
* COPYRIGHT:
|
|
|
|
|
|
*
|
|
|
|
|
|
* This software module was originally developed by Rapha<EFBFBD>l Grosbois and
|
|
|
|
|
|
* Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
|
|
|
|
|
|
* Askel<EFBFBD>f (Ericsson Radio Systems AB); and Bertrand Berthelot, David
|
|
|
|
|
|
* Bouchard, F<EFBFBD>lix Henry, Gerard Mozelle and Patrice Onno (Canon Research
|
|
|
|
|
|
* Centre France S.A) in the course of development of the JPEG2000
|
|
|
|
|
|
* standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
|
|
|
|
|
|
* software module is an implementation of a part of the JPEG 2000
|
|
|
|
|
|
* Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
|
|
|
|
|
|
* Systems AB and Canon Research Centre France S.A (collectively JJ2000
|
|
|
|
|
|
* Partners) agree not to assert against ISO/IEC and users of the JPEG
|
|
|
|
|
|
* 2000 Standard (Users) any of their rights under the copyright, not
|
|
|
|
|
|
* including other intellectual property rights, for this software module
|
|
|
|
|
|
* with respect to the usage by ISO/IEC and Users of this software module
|
|
|
|
|
|
* or modifications thereof for use in hardware or software products
|
|
|
|
|
|
* claiming conformance to the JPEG 2000 Standard. Those intending to use
|
|
|
|
|
|
* this software module in hardware or software products are advised that
|
|
|
|
|
|
* their use may infringe existing patents. The original developers of
|
|
|
|
|
|
* this software module, JJ2000 Partners and ISO/IEC assume no liability
|
|
|
|
|
|
* for use of this software module or modifications thereof. No license
|
|
|
|
|
|
* or right to this software module is granted for non JPEG 2000 Standard
|
|
|
|
|
|
* conforming products. JJ2000 Partners have full right to use this
|
|
|
|
|
|
* software module for his/her own purpose, assign or donate this
|
|
|
|
|
|
* software module to any third party and to inhibit third parties from
|
|
|
|
|
|
* using this software module for non JPEG 2000 Standard conforming
|
|
|
|
|
|
* products. This copyright notice must be included in all copies or
|
|
|
|
|
|
* derivative works of this software module.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Copyright (c) 1999/2000 JJ2000 Partners.
|
|
|
|
|
|
* */
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using CSJ2K.j2k.util;
|
|
|
|
|
|
namespace CSJ2K.j2k.codestream.writer
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> This class implements a buffer for writing bits, with the required bit
|
|
|
|
|
|
/// stuffing policy for the packet headers. The bits are stored in a byte array
|
|
|
|
|
|
/// in the order in which they are written. The byte array is automatically
|
|
|
|
|
|
/// reallocated and enlarged whenever necessary. A BitOutputBuffer object may
|
|
|
|
|
|
/// be reused by calling its 'reset()' method.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// <P>NOTE: The methods implemented in this class are intended to be used only
|
|
|
|
|
|
/// in writing packet heads, since a special bit stuffing procedure is used, as
|
|
|
|
|
|
/// required for the packet heads.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class BitOutputBuffer
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary> Returns the current length of the buffer, in bytes.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// <P>This method is declared final to increase performance.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns> The currebt length of the buffer in bytes.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </returns>
|
|
|
|
|
|
virtual public int Length
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (avbits == 8)
|
|
|
|
|
|
{
|
|
|
|
|
|
// A integral number of bytes
|
|
|
|
|
|
return curbyte;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Some bits in last byte
|
|
|
|
|
|
return curbyte + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary> Returns the byte buffer. This is the internal byte buffer so it should
|
|
|
|
|
|
/// not be modified. Only the first N elements have valid data, where N is
|
|
|
|
|
|
/// the value returned by 'getLength()'
|
|
|
|
|
|
///
|
|
|
|
|
|
/// <P>This method is declared final to increase performance.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns> The internal byte buffer.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </returns>
|
|
|
|
|
|
virtual public byte[] Buffer
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return buf;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>The buffer where we store the data </summary>
|
|
|
|
|
|
internal byte[] buf;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>The position of the current byte to write </summary>
|
|
|
|
|
|
internal int curbyte;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>The number of available bits in the current byte </summary>
|
|
|
|
|
|
internal int avbits = 8;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>The increment size for the buffer, 16 bytes. This is the
|
|
|
|
|
|
/// number of bytes that are added to the buffer each time it is
|
|
|
|
|
|
/// needed to enlarge it.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
// This must be always 6 or larger.
|
|
|
|
|
|
public const int SZ_INCR = 16;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>The initial size for the buffer, 32 bytes. </summary>
|
|
|
|
|
|
public const int SZ_INIT = 32;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Creates a new BitOutputBuffer width a buffer of length
|
|
|
|
|
|
/// 'SZ_INIT'.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public BitOutputBuffer()
|
|
|
|
|
|
{
|
|
|
|
|
|
buf = new byte[SZ_INIT];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Resets the buffer. This rewinds the current position to the start of
|
|
|
|
|
|
/// the buffer and sets all tha data to 0. Note that no new buffer is
|
|
|
|
|
|
/// allocated, so this will affect any data that was returned by the
|
|
|
|
|
|
/// 'getBuffer()' method.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public virtual void reset()
|
|
|
|
|
|
{
|
|
|
|
|
|
//int i;
|
|
|
|
|
|
// Reinit pointers
|
|
|
|
|
|
curbyte = 0;
|
|
|
|
|
|
avbits = 8;
|
|
|
|
|
|
ArrayUtil.byteArraySet(buf, (byte) 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Writes a bit to the buffer at the current position. The value 'bit'
|
|
|
|
|
|
/// must be either 0 or 1, otherwise it corrupts the bits that have been
|
|
|
|
|
|
/// already written. The buffer is enlarged, by 'SZ_INCR' bytes, if
|
|
|
|
|
|
/// necessary.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// <P>This method is declared final to increase performance.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="bit">The bit to write, 0 or 1.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </param>
|
|
|
|
|
|
public void writeBit(int bit)
|
|
|
|
|
|
{
|
|
|
|
|
|
buf[curbyte] |= (byte) (bit << --avbits);
|
|
|
|
|
|
if (avbits > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// There is still place in current byte for next bit
|
|
|
|
|
|
return ;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// End of current byte => goto next
|
|
|
|
|
|
if (buf[curbyte] != (byte) SupportClass.Identity(0xFF))
|
|
|
|
|
|
{
|
|
|
|
|
|
// We don't need bit stuffing
|
|
|
|
|
|
avbits = 8;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// We need to stuff a bit (next MSBit is 0)
|
|
|
|
|
|
avbits = 7;
|
|
|
|
|
|
}
|
|
|
|
|
|
curbyte++;
|
|
|
|
|
|
if (curbyte == buf.Length)
|
|
|
|
|
|
{
|
|
|
|
|
|
// We are at end of 'buf' => extend it
|
|
|
|
|
|
byte[] oldbuf = buf;
|
|
|
|
|
|
buf = new byte[oldbuf.Length + SZ_INCR];
|
2010-08-06 03:11:08 +00:00
|
|
|
|
Array.Copy(oldbuf, 0, buf, 0, oldbuf.Length);
|
2009-09-30 23:50:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Writes the n least significant bits of 'bits' to the buffer at the
|
|
|
|
|
|
/// current position. The least significant bit is written last. The 32-n
|
|
|
|
|
|
/// most significant bits of 'bits' must be 0, otherwise corruption of the
|
|
|
|
|
|
/// buffer will result. The buffer is enlarged, by 'SZ_INCR' bytes, if
|
|
|
|
|
|
/// necessary.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// <P>This method is declared final to increase performance.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="bits">The bits to write.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </param>
|
|
|
|
|
|
/// <param name="n">The number of LSBs in 'bits' to write.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </param>
|
|
|
|
|
|
public void writeBits(int bits, int n)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Check that we have enough place in 'buf' for n bits, and that we do
|
|
|
|
|
|
// not fill last byte, taking into account possibly stuffed bits (max
|
|
|
|
|
|
// 2)
|
|
|
|
|
|
if (((buf.Length - curbyte) << 3) - 8 + avbits <= n + 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Not enough place, extend it
|
|
|
|
|
|
byte[] oldbuf = buf;
|
|
|
|
|
|
buf = new byte[oldbuf.Length + SZ_INCR];
|
2010-08-06 03:11:08 +00:00
|
|
|
|
Array.Copy(oldbuf, 0, buf, 0, oldbuf.Length);
|
2009-09-30 23:50:03 +00:00
|
|
|
|
// SZ_INCR is always 6 or more, so it is enough to hold all the
|
|
|
|
|
|
// new bits plus the ones to come after
|
|
|
|
|
|
}
|
|
|
|
|
|
// Now write the bits
|
|
|
|
|
|
if (n >= avbits)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Complete the current byte
|
|
|
|
|
|
n -= avbits;
|
|
|
|
|
|
buf[curbyte] |= (byte) (bits >> n);
|
|
|
|
|
|
if (buf[curbyte] != (byte) SupportClass.Identity(0xFF))
|
|
|
|
|
|
{
|
|
|
|
|
|
// We don't need bit stuffing
|
|
|
|
|
|
avbits = 8;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// We need to stuff a bit (next MSBit is 0)
|
|
|
|
|
|
avbits = 7;
|
|
|
|
|
|
}
|
|
|
|
|
|
curbyte++;
|
|
|
|
|
|
// Write whole bytes
|
|
|
|
|
|
while (n >= avbits)
|
|
|
|
|
|
{
|
|
|
|
|
|
n -= avbits;
|
|
|
|
|
|
// CONVERSION PROBLEM?
|
|
|
|
|
|
buf[curbyte] |= (byte)((bits >> n) & (~ (1 << avbits)));
|
|
|
|
|
|
if (buf[curbyte] != (byte) SupportClass.Identity(0xFF))
|
|
|
|
|
|
{
|
|
|
|
|
|
// We don't need bit
|
|
|
|
|
|
// stuffing
|
|
|
|
|
|
avbits = 8;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// We need to stuff a bit (next MSBit is 0)
|
|
|
|
|
|
avbits = 7;
|
|
|
|
|
|
}
|
|
|
|
|
|
curbyte++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// Finish last byte (we know that now n < avbits)
|
|
|
|
|
|
if (n > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
avbits -= n;
|
|
|
|
|
|
buf[curbyte] |= (byte) ((bits & ((1 << n) - 1)) << avbits);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (avbits == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Last byte is full
|
|
|
|
|
|
if (buf[curbyte] != (byte) SupportClass.Identity(0xFF))
|
|
|
|
|
|
{
|
|
|
|
|
|
// We don't need bit stuffing
|
|
|
|
|
|
avbits = 8;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// We need to stuff a bit (next MSBit is 0)
|
|
|
|
|
|
avbits = 7;
|
|
|
|
|
|
}
|
|
|
|
|
|
curbyte++; // We already ensured that we have enough place
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Returns the byte buffer data in a new array. This is a copy of the
|
|
|
|
|
|
/// internal byte buffer. If 'data' is non-null it is used to return the
|
|
|
|
|
|
/// data. This array should be large enough to contain all the data,
|
|
|
|
|
|
/// otherwise a IndexOutOfBoundsException is thrown by the Java system. The
|
|
|
|
|
|
/// number of elements returned is what 'getLength()' returns.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="data">If non-null this array is used to return the data, which
|
|
|
|
|
|
/// mus be large enough. Otherwise a new one is created and returned.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </param>
|
|
|
|
|
|
/// <returns> The byte buffer data.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </returns>
|
|
|
|
|
|
public virtual byte[] toByteArray(byte[] data)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (data == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
data = new byte[(avbits == 8)?curbyte:curbyte + 1];
|
|
|
|
|
|
}
|
2010-08-06 03:11:08 +00:00
|
|
|
|
Array.Copy(buf, 0, data, 0, (avbits == 8)?curbyte:curbyte + 1);
|
2009-09-30 23:50:03 +00:00
|
|
|
|
return data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> Prints information about this object for debugging purposes
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns> Information about the object.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </returns>
|
|
|
|
|
|
public override System.String ToString()
|
|
|
|
|
|
{
|
|
|
|
|
|
return "bits written = " + (curbyte * 8 + (8 - avbits)) + ", curbyte = " + curbyte + ", avbits = " + avbits;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|