001: /*
002: * $RCSfile: BitToByteOutput.java,v $
003: * $Revision: 1.1 $
004: * $Date: 2005/02/11 05:02:07 $
005: * $State: Exp $
006: *
007: * Class: BitToByteOutput
008: *
009: * Description: Adapter to perform bit based output on a byte
010: * based one.
011: *
012: *
013: *
014: * COPYRIGHT:
015: *
016: * This software module was originally developed by Raphaël Grosbois and
017: * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
018: * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
019: * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
020: * Centre France S.A) in the course of development of the JPEG2000
021: * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
022: * software module is an implementation of a part of the JPEG 2000
023: * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
024: * Systems AB and Canon Research Centre France S.A (collectively JJ2000
025: * Partners) agree not to assert against ISO/IEC and users of the JPEG
026: * 2000 Standard (Users) any of their rights under the copyright, not
027: * including other intellectual property rights, for this software module
028: * with respect to the usage by ISO/IEC and Users of this software module
029: * or modifications thereof for use in hardware or software products
030: * claiming conformance to the JPEG 2000 Standard. Those intending to use
031: * this software module in hardware or software products are advised that
032: * their use may infringe existing patents. The original developers of
033: * this software module, JJ2000 Partners and ISO/IEC assume no liability
034: * for use of this software module or modifications thereof. No license
035: * or right to this software module is granted for non JPEG 2000 Standard
036: * conforming products. JJ2000 Partners have full right to use this
037: * software module for his/her own purpose, assign or donate this
038: * software module to any third party and to inhibit third parties from
039: * using this software module for non JPEG 2000 Standard conforming
040: * products. This copyright notice must be included in all copies or
041: * derivative works of this software module.
042: *
043: * Copyright (c) 1999/2000 JJ2000 Partners.
044: * */
045: package jj2000.j2k.entropy.encoder;
046:
047: import jj2000.j2k.io.*;
048:
049: /**
050: * This class provides an adapter to perform bit based output on byte based
051: * output objects that inherit from a 'ByteOutputBuffer' class. This class
052: * implements the bit stuffing policy needed for the 'selective arithmetic
053: * coding bypass' mode of the entropy coder. This class also delays the output
054: * of a trailing 0xFF, since they are synthetized be the decoder.
055: * */
056: class BitToByteOutput {
057:
058: /** Whether or not predictable termination is requested. This value is
059: * important when the last byte before termination is an 0xFF */
060: private boolean isPredTerm = false;
061:
062: /** The alternating sequence of 0's and 1's used for byte padding */
063: static final int PAD_SEQ = 0x2A;
064:
065: /** Flag that indicates if an FF has been delayed */
066: boolean delFF = false;
067:
068: /** The byte based output */
069: ByteOutputBuffer out;
070:
071: /** The bit buffer */
072: int bbuf;
073:
074: /** The position of the next bit to put in the bit buffer. When it is 7
075: * the bit buffer 'bbuf' is empty. The value should always be between 7
076: * and 0 (i.e. if it gets to -1, the bit buffer should be immediately
077: * written to the byte output). */
078: int bpos = 7;
079:
080: /** The number of written bytes (excluding the bit buffer) */
081: int nb = 0;
082:
083: /**
084: * Instantiates a new 'BitToByteOutput' object that uses 'out' as the
085: * underlying byte based output.
086: *
087: * @param out The underlying byte based output
088: * */
089: BitToByteOutput(ByteOutputBuffer out) {
090: this .out = out;
091: }
092:
093: /**
094: * Writes to the bit stream the symbols contained in the 'symbuf'
095: * buffer. The least significant bit of each element in 'symbuf'is
096: * written.
097: *
098: * @param symbuf The symbols to write
099: *
100: * @param nsym The number of symbols in symbuf
101: * */
102: final void writeBits(int[] symbuf, int nsym) {
103: int i;
104: int bbuf, bpos;
105: bbuf = this .bbuf;
106: bpos = this .bpos;
107: // Write symbol by symbol to bit buffer
108: for (i = 0; i < nsym; i++) {
109: bbuf |= (symbuf[i] & 0x01) << (bpos--);
110: if (bpos < 0) { // Bit buffer is full, write it
111: if (bbuf != 0xFF) { // No bit-stuffing needed
112: if (delFF) { // Output delayed 0xFF if any
113: out.write(0xFF);
114: delFF = false;
115: nb++;
116: }
117: out.write(bbuf);
118: nb++;
119: bpos = 7;
120: } else { // We need to do bit stuffing on next byte
121: delFF = true;
122: bpos = 6; // One less bit in next byte
123: }
124: bbuf = 0;
125: }
126: }
127: this .bbuf = bbuf;
128: this .bpos = bpos;
129: }
130:
131: /**
132: * Write a bit to the output. The least significant bit of 'bit' is
133: * written to the output.
134: *
135: * @param bit
136: * */
137: final void writeBit(int bit) {
138: bbuf |= (bit & 0x01) << (bpos--);
139: if (bpos < 0) {
140: if (bbuf != 0xFF) { // No bit-stuffing needed
141: if (delFF) { // Output delayed 0xFF if any
142: out.write(0xFF);
143: delFF = false;
144: nb++;
145: }
146: // Output the bit buffer
147: out.write(bbuf);
148: nb++;
149: bpos = 7;
150: } else { // We need to do bit stuffing on next byte
151: delFF = true;
152: bpos = 6; // One less bit in next byte
153: }
154: bbuf = 0;
155: }
156: }
157:
158: /**
159: * Writes the contents of the bit buffer and byte aligns the output by
160: * filling bits with an alternating sequence of 0's and 1's.
161: * */
162: void flush() {
163: if (delFF) { // There was a bit stuffing
164: if (bpos != 6) { // Bit buffer is not empty
165: // Output delayed 0xFF
166: out.write(0xFF);
167: delFF = false;
168: nb++;
169: // Pad to byte boundary with an alternating sequence of 0's
170: // and 1's.
171: bbuf |= (PAD_SEQ >>> (6 - bpos));
172: // Output the bit buffer
173: out.write(bbuf);
174: nb++;
175: bpos = 7;
176: bbuf = 0;
177: } else if (isPredTerm) {
178: out.write(0xFF);
179: nb++;
180: out.write(0x2A);
181: nb++;
182: bpos = 7;
183: bbuf = 0;
184: delFF = false;
185: }
186: } else { // There was no bit stuffing
187: if (bpos != 7) { // Bit buffer is not empty
188: // Pad to byte boundary with an alternating sequence of 0's and
189: // 1's.
190: bbuf |= (PAD_SEQ >>> (6 - bpos));
191: // Output the bit buffer (bbuf can not be 0xFF)
192: out.write(bbuf);
193: nb++;
194: bpos = 7;
195: bbuf = 0;
196: }
197: }
198: }
199:
200: /**
201: * Terminates the bit stream by calling 'flush()' and then 'reset()'.
202: * */
203: public int terminate() {
204: flush();
205: int savedNb = nb;
206: reset();
207: return savedNb;
208: }
209:
210: /**
211: * Resets the bit buffer to empty, without writing anything to the
212: * underlying byte output, and resets the byte count. The underlying byte
213: * output is NOT reset.
214: * */
215: void reset() {
216: delFF = false;
217: bpos = 7;
218: bbuf = 0;
219: nb = 0;
220: }
221:
222: /**
223: * Returns the length, in bytes, of the output bit stream as written by
224: * this object. If the output bit stream does not have an integer number
225: * of bytes in length then it is rounded to the next integer.
226: *
227: * @return The length, in bytes, of the output bit stream.
228: * */
229: int length() {
230: if (delFF) {
231: // If bit buffer is empty we just need 'nb' bytes. If not we need
232: // the delayed FF and the padded bit buffer.
233: return nb + 2;
234: } else {
235: // If the bit buffer is empty, we just need 'nb' bytes. If not, we
236: // add length of the padded bit buffer
237: return nb + ((bpos == 7) ? 0 : 1);
238: }
239: }
240:
241: /**
242: * Set the flag according to whether or not the predictable termination is
243: * requested.
244: *
245: * @param isPredTerm Whether or not predictable termination is requested.
246: * */
247: void setPredTerm(boolean isPredTerm) {
248: this.isPredTerm = isPredTerm;
249: }
250:
251: }
|