corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * CVS identifier:
3 *
4 * $Id: BitOutputBuffer.java,v 1.9 2002/07/19 12:40:05 grosbois Exp $
5 *
6 * Class: BitOutputBuffer
7 *
8 * Description: <short description of class>
9 *
10 *
11 *
12 * COPYRIGHT:
13 *
14 * This software module was originally developed by Raphaël Grosbois and
15 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
16 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
17 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
18 * Centre France S.A) in the course of development of the JPEG2000
19 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
20 * software module is an implementation of a part of the JPEG 2000
21 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
22 * Systems AB and Canon Research Centre France S.A (collectively JJ2000
23 * Partners) agree not to assert against ISO/IEC and users of the JPEG
24 * 2000 Standard (Users) any of their rights under the copyright, not
25 * including other intellectual property rights, for this software module
26 * with respect to the usage by ISO/IEC and Users of this software module
27 * or modifications thereof for use in hardware or software products
28 * claiming conformance to the JPEG 2000 Standard. Those intending to use
29 * this software module in hardware or software products are advised that
30 * their use may infringe existing patents. The original developers of
31 * this software module, JJ2000 Partners and ISO/IEC assume no liability
32 * for use of this software module or modifications thereof. No license
33 * or right to this software module is granted for non JPEG 2000 Standard
34 * conforming products. JJ2000 Partners have full right to use this
35 * software module for his/her own purpose, assign or donate this
36 * software module to any third party and to inhibit third parties from
37 * using this software module for non JPEG 2000 Standard conforming
38 * products. This copyright notice must be included in all copies or
39 * derivative works of this software module.
40 *
41 * Copyright (c) 1999/2000 JJ2000 Partners.
42 * */
43 using System;
44 using CSJ2K.j2k.util;
45 namespace CSJ2K.j2k.codestream.writer
46 {
47  
48 /// <summary> This class implements a buffer for writing bits, with the required bit
49 /// stuffing policy for the packet headers. The bits are stored in a byte array
50 /// in the order in which they are written. The byte array is automatically
51 /// reallocated and enlarged whenever necessary. A BitOutputBuffer object may
52 /// be reused by calling its 'reset()' method.
53 ///
54 /// <P>NOTE: The methods implemented in this class are intended to be used only
55 /// in writing packet heads, since a special bit stuffing procedure is used, as
56 /// required for the packet heads.
57 ///
58 /// </summary>
59 public class BitOutputBuffer
60 {
61 /// <summary> Returns the current length of the buffer, in bytes.
62 ///
63 /// <P>This method is declared final to increase performance.
64 ///
65 /// </summary>
66 /// <returns> The currebt length of the buffer in bytes.
67 ///
68 /// </returns>
69 virtual public int Length
70 {
71 get
72 {
73 if (avbits == 8)
74 {
75 // A integral number of bytes
76 return curbyte;
77 }
78 else
79 {
80 // Some bits in last byte
81 return curbyte + 1;
82 }
83 }
84  
85 }
86 /// <summary> Returns the byte buffer. This is the internal byte buffer so it should
87 /// not be modified. Only the first N elements have valid data, where N is
88 /// the value returned by 'getLength()'
89 ///
90 /// <P>This method is declared final to increase performance.
91 ///
92 /// </summary>
93 /// <returns> The internal byte buffer.
94 ///
95 /// </returns>
96 virtual public byte[] Buffer
97 {
98 get
99 {
100 return buf;
101 }
102  
103 }
104  
105 /// <summary>The buffer where we store the data </summary>
106 internal byte[] buf;
107  
108 /// <summary>The position of the current byte to write </summary>
109 internal int curbyte;
110  
111 /// <summary>The number of available bits in the current byte </summary>
112 internal int avbits = 8;
113  
114 /// <summary>The increment size for the buffer, 16 bytes. This is the
115 /// number of bytes that are added to the buffer each time it is
116 /// needed to enlarge it.
117 /// </summary>
118 // This must be always 6 or larger.
119 public const int SZ_INCR = 16;
120  
121 /// <summary>The initial size for the buffer, 32 bytes. </summary>
122 public const int SZ_INIT = 32;
123  
124 /// <summary> Creates a new BitOutputBuffer width a buffer of length
125 /// 'SZ_INIT'.
126 ///
127 /// </summary>
128 public BitOutputBuffer()
129 {
130 buf = new byte[SZ_INIT];
131 }
132  
133 /// <summary> Resets the buffer. This rewinds the current position to the start of
134 /// the buffer and sets all tha data to 0. Note that no new buffer is
135 /// allocated, so this will affect any data that was returned by the
136 /// 'getBuffer()' method.
137 ///
138 /// </summary>
139 public virtual void reset()
140 {
141 //int i;
142 // Reinit pointers
143 curbyte = 0;
144 avbits = 8;
145 ArrayUtil.byteArraySet(buf, (byte) 0);
146 }
147  
148 /// <summary> Writes a bit to the buffer at the current position. The value 'bit'
149 /// must be either 0 or 1, otherwise it corrupts the bits that have been
150 /// already written. The buffer is enlarged, by 'SZ_INCR' bytes, if
151 /// necessary.
152 ///
153 /// <P>This method is declared final to increase performance.
154 ///
155 /// </summary>
156 /// <param name="bit">The bit to write, 0 or 1.
157 ///
158 /// </param>
159 public void writeBit(int bit)
160 {
161 buf[curbyte] |= (byte) (bit << --avbits);
162 if (avbits > 0)
163 {
164 // There is still place in current byte for next bit
165 return ;
166 }
167 else
168 {
169 // End of current byte => goto next
170 if (buf[curbyte] != (byte) SupportClass.Identity(0xFF))
171 {
172 // We don't need bit stuffing
173 avbits = 8;
174 }
175 else
176 {
177 // We need to stuff a bit (next MSBit is 0)
178 avbits = 7;
179 }
180 curbyte++;
181 if (curbyte == buf.Length)
182 {
183 // We are at end of 'buf' => extend it
184 byte[] oldbuf = buf;
185 buf = new byte[oldbuf.Length + SZ_INCR];
186 Array.Copy(oldbuf, 0, buf, 0, oldbuf.Length);
187 }
188 }
189 }
190  
191 /// <summary> Writes the n least significant bits of 'bits' to the buffer at the
192 /// current position. The least significant bit is written last. The 32-n
193 /// most significant bits of 'bits' must be 0, otherwise corruption of the
194 /// buffer will result. The buffer is enlarged, by 'SZ_INCR' bytes, if
195 /// necessary.
196 ///
197 /// <P>This method is declared final to increase performance.
198 ///
199 /// </summary>
200 /// <param name="bits">The bits to write.
201 ///
202 /// </param>
203 /// <param name="n">The number of LSBs in 'bits' to write.
204 ///
205 /// </param>
206 public void writeBits(int bits, int n)
207 {
208 // Check that we have enough place in 'buf' for n bits, and that we do
209 // not fill last byte, taking into account possibly stuffed bits (max
210 // 2)
211 if (((buf.Length - curbyte) << 3) - 8 + avbits <= n + 2)
212 {
213 // Not enough place, extend it
214 byte[] oldbuf = buf;
215 buf = new byte[oldbuf.Length + SZ_INCR];
216 Array.Copy(oldbuf, 0, buf, 0, oldbuf.Length);
217 // SZ_INCR is always 6 or more, so it is enough to hold all the
218 // new bits plus the ones to come after
219 }
220 // Now write the bits
221 if (n >= avbits)
222 {
223 // Complete the current byte
224 n -= avbits;
225 buf[curbyte] |= (byte) (bits >> n);
226 if (buf[curbyte] != (byte) SupportClass.Identity(0xFF))
227 {
228 // We don't need bit stuffing
229 avbits = 8;
230 }
231 else
232 {
233 // We need to stuff a bit (next MSBit is 0)
234 avbits = 7;
235 }
236 curbyte++;
237 // Write whole bytes
238 while (n >= avbits)
239 {
240 n -= avbits;
241 // CONVERSION PROBLEM?
242 buf[curbyte] |= (byte)((bits >> n) & (~ (1 << avbits)));
243 if (buf[curbyte] != (byte) SupportClass.Identity(0xFF))
244 {
245 // We don't need bit
246 // stuffing
247 avbits = 8;
248 }
249 else
250 {
251 // We need to stuff a bit (next MSBit is 0)
252 avbits = 7;
253 }
254 curbyte++;
255 }
256 }
257 // Finish last byte (we know that now n < avbits)
258 if (n > 0)
259 {
260 avbits -= n;
261 buf[curbyte] |= (byte) ((bits & ((1 << n) - 1)) << avbits);
262 }
263 if (avbits == 0)
264 {
265 // Last byte is full
266 if (buf[curbyte] != (byte) SupportClass.Identity(0xFF))
267 {
268 // We don't need bit stuffing
269 avbits = 8;
270 }
271 else
272 {
273 // We need to stuff a bit (next MSBit is 0)
274 avbits = 7;
275 }
276 curbyte++; // We already ensured that we have enough place
277 }
278 }
279  
280 /// <summary> Returns the byte buffer data in a new array. This is a copy of the
281 /// internal byte buffer. If 'data' is non-null it is used to return the
282 /// data. This array should be large enough to contain all the data,
283 /// otherwise a IndexOutOfBoundsException is thrown by the Java system. The
284 /// number of elements returned is what 'getLength()' returns.
285 ///
286 /// </summary>
287 /// <param name="data">If non-null this array is used to return the data, which
288 /// mus be large enough. Otherwise a new one is created and returned.
289 ///
290 /// </param>
291 /// <returns> The byte buffer data.
292 ///
293 /// </returns>
294 public virtual byte[] toByteArray(byte[] data)
295 {
296 if (data == null)
297 {
298 data = new byte[(avbits == 8)?curbyte:curbyte + 1];
299 }
300 Array.Copy(buf, 0, data, 0, (avbits == 8)?curbyte:curbyte + 1);
301 return data;
302 }
303  
304 /// <summary> Prints information about this object for debugging purposes
305 ///
306 /// </summary>
307 /// <returns> Information about the object.
308 ///
309 /// </returns>
310 public override System.String ToString()
311 {
312 return "bits written = " + (curbyte * 8 + (8 - avbits)) + ", curbyte = " + curbyte + ", avbits = " + avbits;
313 }
314 }
315 }