KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > imageio > plugins > jpeg > JPEGBuffer


1 /*
2  * @(#)JPEGBuffer.java 1.8 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.imageio.plugins.jpeg;
9
10 import javax.imageio.stream.ImageInputStream JavaDoc;
11 import javax.imageio.IIOException JavaDoc;
12
13 import java.io.IOException JavaDoc;
14
15 /**
16  * A class wrapping a buffer and its state. For efficiency,
17  * the members are made visible to other classes in this package.
18  */

19 class JPEGBuffer {
20
21     private boolean debug = false;
22
23     /**
24      * The size of the buffer. This is large enough to hold all
25      * known marker segments (other than thumbnails and icc profiles)
26      */

27     final int BUFFER_SIZE = 4096;
28
29     /**
30      * The actual buffer.
31      */

32     byte [] buf;
33
34     /**
35      * The number of bytes available for reading from the buffer.
36      * Anytime data is read from the buffer, this should be updated.
37      */

38     int bufAvail;
39     
40     /**
41      * A pointer to the next available byte in the buffer. This is
42      * used to read data from the buffer and must be updated to
43      * move through the buffer.
44      */

45     int bufPtr;
46     
47     /**
48      * The ImageInputStream buffered.
49      */

50     ImageInputStream JavaDoc iis;
51
52     JPEGBuffer (ImageInputStream JavaDoc iis) {
53         buf = new byte[BUFFER_SIZE];
54         bufAvail = 0;
55         bufPtr = 0;
56         this.iis = iis;
57     }
58
59     /**
60      * Ensures that there are at least <code>count</code> bytes available
61      * in the buffer, loading more data and moving any remaining
62      * bytes to the front. A count of 0 means to just fill the buffer.
63      * If the count is larger than the buffer size, just fills the buffer.
64      * If the end of the stream is encountered before a non-0 count can
65      * be satisfied, an <code>IIOException</code> is thrown with the
66      * message "Image Format Error".
67      */

68     void loadBuf(int count) throws IOException JavaDoc {
69         if (debug) {
70             System.out.print("loadbuf called with ");
71             System.out.print("count " + count + ", ");
72             System.out.println("bufAvail " + bufAvail + ", ");
73         }
74         if (count != 0) {
75             if (bufAvail >= count) { // have enough
76
return;
77             }
78         } else {
79             if (bufAvail == BUFFER_SIZE) { // already full
80
return;
81             }
82         }
83         // First copy any remaining bytes down to the beginning
84
if ((bufAvail > 0) && (bufAvail < BUFFER_SIZE)) {
85             System.arraycopy(buf, bufPtr, buf, 0, bufAvail);
86         }
87         // Now fill the rest of the buffer
88
int ret = iis.read(buf, bufAvail, buf.length - bufAvail);
89         if (debug) {
90             System.out.println("iis.read returned " + ret);
91         }
92         if (ret != -1) {
93             bufAvail += ret;
94         }
95         bufPtr = 0;
96         int minimum = Math.min(BUFFER_SIZE, count);
97         if (bufAvail < minimum) {
98             throw new IIOException JavaDoc ("Image Format Error");
99         }
100     }
101
102     /**
103      * Fills the data array from the stream, starting with
104      * the buffer and then reading directly from the stream
105      * if necessary. The buffer is left in an appropriate
106      * state. If the end of the stream is encountered, an
107      * <code>IIOException</code> is thrown with the
108      * message "Image Format Error".
109      */

110     void readData(byte [] data) throws IOException JavaDoc {
111         int count = data.length;
112         // First see what's left in the buffer.
113
if (bufAvail >= count) { // It's enough
114
System.arraycopy(buf, bufPtr, data, 0, count);
115             bufAvail -= count;
116             bufPtr += count;
117             return;
118         }
119         int offset = 0;
120         if (bufAvail > 0) { // Some there, but not enough
121
System.arraycopy(buf, bufPtr, data, 0, bufAvail);
122             offset = bufAvail;
123             count -= bufAvail;
124             bufAvail = 0;
125             bufPtr = 0;
126         }
127         // Now read the rest directly from the stream
128
if (iis.read(data, offset, count) != count) {
129             throw new IIOException JavaDoc ("Image format Error");
130         }
131     }
132
133     /**
134      * Skips <code>count</code> bytes, leaving the buffer
135      * in an appropriate state. If the end of the stream is
136      * encountered, an <code>IIOException</code> is thrown with the
137      * message "Image Format Error".
138      */

139     void skipData(int count) throws IOException JavaDoc {
140         // First see what's left in the buffer.
141
if (bufAvail >= count) { // It's enough
142
bufAvail -= count;
143             bufPtr += count;
144             return;
145         }
146         if (bufAvail > 0) { // Some there, but not enough
147
count -= bufAvail;
148             bufAvail = 0;
149             bufPtr = 0;
150         }
151         // Now read the rest directly from the stream
152
if (iis.skipBytes(count) != count) {
153             throw new IIOException JavaDoc ("Image format Error");
154         }
155     }
156
157     /**
158      * Push back the remaining contents of the buffer by
159      * repositioning the input stream.
160      */

161     void pushBack() throws IOException JavaDoc {
162         iis.seek(iis.getStreamPosition()-bufAvail);
163         bufAvail = 0;
164         bufPtr = 0;
165     }
166
167     /**
168      * Return the stream position corresponding to the next
169      * available byte in the buffer.
170      */

171     long getStreamPosition() throws IOException JavaDoc {
172         return (iis.getStreamPosition()-bufAvail);
173     }
174
175     /**
176      * Scan the buffer until the next 0xff byte, reloading
177      * the buffer as necessary. The buffer position is left
178      * pointing to the first non-0xff byte after a run of
179      * 0xff bytes. If the end of the stream is encountered,
180      * an EOI marker is inserted into the buffer and <code>true</code>
181      * is returned. Otherwise returns <code>false</code>.
182      */

183     boolean scanForFF(JPEGImageReader reader) throws IOException JavaDoc {
184         boolean retval = false;
185         boolean foundFF = false;
186         while (foundFF == false) {
187             while (bufAvail > 0) {
188                 if ((buf[bufPtr++] & 0xff) == 0xff) {
189                     bufAvail--;
190                     foundFF = true;
191                     break; // out of inner while
192
}
193                 bufAvail--;
194             }
195             // Reload the buffer and keep going
196
loadBuf(0);
197             // Skip any remaining pad bytes
198
if (foundFF == true) {
199                 while ((bufAvail > 0) && (buf[bufPtr] & 0xff) == 0xff) {
200                     bufPtr++; // Only if it still is 0xff
201
bufAvail--;
202                 }
203             }
204             if (bufAvail == 0) { // Premature EOF
205
// send out a warning, but treat it as EOI
206
//reader.warningOccurred(JPEGImageReader.WARNING_NO_EOI);
207
retval = true;
208                 buf[0] = (byte)JPEG.EOI;
209                 bufAvail = 1;
210                 bufPtr = 0;
211                 foundFF = true;
212             }
213         }
214         return retval;
215     }
216         
217     /**
218      * Prints the contents of the buffer, in hex.
219      * @param count the number of bytes to print,
220      * starting at the current available byte.
221      */

222     void print(int count) {
223         System.out.print("buffer has ");
224         System.out.print(bufAvail);
225         System.out.println(" bytes available");
226         if (bufAvail < count) {
227             count = bufAvail;
228         }
229         for (int ptr = bufPtr; count > 0; count--) {
230             int val = (int)buf[ptr++] & 0xff;
231             System.out.print(" " + Integer.toHexString(val));
232         }
233         System.out.println();
234     }
235     
236 }
237
238
Popular Tags