001/* 002 * $RCSfile: BitOutputBuffer.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:02 $ 005 * $State: Exp $ 006 * 007 * Class: BitOutputBuffer 008 * 009 * Description: <short description of class> 010 * 011 * 012 * 013 * COPYRIGHT: 014 * 015 * This software module was originally developed by Raphaël Grosbois and 016 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel 017 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David 018 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research 019 * Centre France S.A) in the course of development of the JPEG2000 020 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This 021 * software module is an implementation of a part of the JPEG 2000 022 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio 023 * Systems AB and Canon Research Centre France S.A (collectively JJ2000 024 * Partners) agree not to assert against ISO/IEC and users of the JPEG 025 * 2000 Standard (Users) any of their rights under the copyright, not 026 * including other intellectual property rights, for this software module 027 * with respect to the usage by ISO/IEC and Users of this software module 028 * or modifications thereof for use in hardware or software products 029 * claiming conformance to the JPEG 2000 Standard. Those intending to use 030 * this software module in hardware or software products are advised that 031 * their use may infringe existing patents. The original developers of 032 * this software module, JJ2000 Partners and ISO/IEC assume no liability 033 * for use of this software module or modifications thereof. No license 034 * or right to this software module is granted for non JPEG 2000 Standard 035 * conforming products. JJ2000 Partners have full right to use this 036 * software module for his/her own purpose, assign or donate this 037 * software module to any third party and to inhibit third parties from 038 * using this software module for non JPEG 2000 Standard conforming 039 * products. This copyright notice must be included in all copies or 040 * derivative works of this software module. 041 * 042 * Copyright (c) 1999/2000 JJ2000 Partners. 043 * */ 044package jj2000.j2k.codestream.writer; 045 046import jj2000.j2k.util.*; 047 048/** 049 * This class implements a buffer for writing bits, with the required bit 050 * stuffing policy for the packet headers. The bits are stored in a byte array 051 * in the order in which they are written. The byte array is automatically 052 * reallocated and enlarged whenever necessary. A BitOutputBuffer object may 053 * be reused by calling its 'reset()' method. 054 * 055 * <P>NOTE: The methods implemented in this class are intended to be used only 056 * in writing packet heads, since a special bit stuffing procedure is used, as 057 * required for the packet heads. 058 * */ 059public class BitOutputBuffer { 060 061 /** The buffer where we store the data */ 062 byte buf[]; 063 064 /** The position of the current byte to write */ 065 int curbyte; 066 067 /** The number of available bits in the current byte */ 068 int avbits = 8; 069 070 /** The increment size for the buffer, 16 bytes. This is the 071 * number of bytes that are added to the buffer each time it is 072 * needed to enlarge it.*/ 073 // This must be always 6 or larger. 074 public final static int SZ_INCR = 16; 075 076 /** The initial size for the buffer, 32 bytes. */ 077 public final static int SZ_INIT = 32; 078 079 /** 080 * Creates a new BitOutputBuffer width a buffer of length 081 * 'SZ_INIT'. 082 * */ 083 public BitOutputBuffer() { 084 buf = new byte[SZ_INIT]; 085 } 086 087 /** 088 * Resets the buffer. This rewinds the current position to the start of 089 * the buffer and sets all tha data to 0. Note that no new buffer is 090 * allocated, so this will affect any data that was returned by the 091 * 'getBuffer()' method. 092 * */ 093 public void reset() { 094 int i; 095 // Reinit pointers 096 curbyte = 0; 097 avbits = 8; 098 ArrayUtil.byteArraySet(buf,(byte)0); 099 } 100 101 /** 102 * Writes a bit to the buffer at the current position. The value 'bit' 103 * must be either 0 or 1, otherwise it corrupts the bits that have been 104 * already written. The buffer is enlarged, by 'SZ_INCR' bytes, if 105 * necessary. 106 * 107 * <P>This method is declared final to increase performance. 108 * 109 * @param bit The bit to write, 0 or 1. 110 * */ 111 public final void writeBit(int bit) { 112 buf[curbyte] |= bit << --avbits; 113 if (avbits > 0) { 114 // There is still place in current byte for next bit 115 return; 116 } 117 else { // End of current byte => goto next 118 if (buf[curbyte] != (byte) 0xFF) { // We don't need bit stuffing 119 avbits = 8; 120 } 121 else { // We need to stuff a bit (next MSBit is 0) 122 avbits = 7; 123 } 124 curbyte++; 125 if (curbyte == buf.length) { 126 // We are at end of 'buf' => extend it 127 byte oldbuf[] = buf; 128 buf = new byte[oldbuf.length+SZ_INCR]; 129 System.arraycopy(oldbuf,0,buf,0,oldbuf.length); 130 } 131 } 132 } 133 134 /** 135 * Writes the n least significant bits of 'bits' to the buffer at the 136 * current position. The least significant bit is written last. The 32-n 137 * most significant bits of 'bits' must be 0, otherwise corruption of the 138 * buffer will result. The buffer is enlarged, by 'SZ_INCR' bytes, if 139 * necessary. 140 * 141 * <P>This method is declared final to increase performance. 142 * 143 * @param bits The bits to write. 144 * 145 * @param n The number of LSBs in 'bits' to write. 146 * */ 147 public final void writeBits(int bits, int n) { 148 // Check that we have enough place in 'buf' for n bits, and that we do 149 // not fill last byte, taking into account possibly stuffed bits (max 150 // 2) 151 if (((buf.length-curbyte)<<3)-8+avbits <= n+2) { 152 // Not enough place, extend it 153 byte oldbuf[] = buf; 154 buf = new byte[oldbuf.length+SZ_INCR]; 155 System.arraycopy(oldbuf,0,buf,0,oldbuf.length); 156 // SZ_INCR is always 6 or more, so it is enough to hold all the 157 // new bits plus the ones to come after 158 } 159 // Now write the bits 160 if (n >= avbits) { 161 // Complete the current byte 162 n -= avbits; 163 buf[curbyte] |= bits >> n; 164 if (buf[curbyte] != (byte) 0xFF) { // We don't need bit stuffing 165 avbits = 8; 166 } 167 else { // We need to stuff a bit (next MSBit is 0) 168 avbits = 7; 169 } 170 curbyte++; 171 // Write whole bytes 172 while (n >= avbits) { 173 n -= avbits; 174 buf[curbyte] |= (bits >> n) & (~(1 << avbits)); 175 if (buf[curbyte] != (byte) 0xFF) { // We don't need bit 176 // stuffing 177 avbits = 8; 178 } 179 else { // We need to stuff a bit (next MSBit is 0) 180 avbits = 7; 181 } 182 curbyte++; 183 } 184 } 185 // Finish last byte (we know that now n < avbits) 186 if (n > 0) { 187 avbits -= n; 188 buf[curbyte] |= (bits & ((1<<n)-1)) << avbits; 189 } 190 if (avbits == 0) { // Last byte is full 191 if (buf[curbyte] != (byte) 0xFF) { // We don't need bit stuffing 192 avbits = 8; 193 } 194 else { // We need to stuff a bit (next MSBit is 0) 195 avbits = 7; 196 } 197 curbyte++; // We already ensured that we have enough place 198 } 199 } 200 201 /** 202 * Returns the current length of the buffer, in bytes. 203 * 204 * <P>This method is declared final to increase performance. 205 * 206 * @return The currebt length of the buffer in bytes. 207 * */ 208 public final int getLength() { 209 if (avbits == 8) { // A integral number of bytes 210 return curbyte; 211 } 212 else { // Some bits in last byte 213 return curbyte+1; 214 } 215 } 216 217 /** 218 * Returns the byte buffer. This is the internal byte buffer so it should 219 * not be modified. Only the first N elements have valid data, where N is 220 * the value returned by 'getLength()' 221 * 222 * <P>This method is declared final to increase performance. 223 * 224 * @return The internal byte buffer. 225 * */ 226 public final byte[] getBuffer() { 227 return buf; 228 } 229 230 /** 231 * Returns the byte buffer data in a new array. This is a copy of the 232 * internal byte buffer. If 'data' is non-null it is used to return the 233 * data. This array should be large enough to contain all the data, 234 * otherwise a IndexOutOfBoundsException is thrown by the Java system. The 235 * number of elements returned is what 'getLength()' returns. 236 * 237 * @param data If non-null this array is used to return the data, which 238 * mus be large enough. Otherwise a new one is created and returned. 239 * 240 * @return The byte buffer data. 241 * */ 242 public byte[] toByteArray(byte data[]) { 243 if (data == null) { 244 data = new byte[(avbits==8)?curbyte:curbyte+1]; 245 } 246 System.arraycopy(buf,0,data,0,(avbits==8)?curbyte:curbyte+1); 247 return data; 248 } 249 250 /** 251 * Prints information about this object for debugging purposes 252 * 253 * @return Information about the object. 254 * */ 255 public String toString() { 256 return "bits written = "+(curbyte*8+(8-avbits))+ 257 ", curbyte = "+curbyte+", avbits = "+avbits; 258 } 259}