-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathByteArrayImageInputStream.java
More file actions
215 lines (197 loc) · 6.95 KB
/
ByteArrayImageInputStream.java
File metadata and controls
215 lines (197 loc) · 6.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
* @(#)ByteArrayImageInputStream.java
*
* Copyright (c) 2008-2011 Werner Randelshofer, Immensee, Switzerland.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
*/
import java.io.IOException;
import java.nio.ByteOrder;
/**
* A {@code ByteArrayImageInputStream} contains
* an internal buffer that contains bytes that
* may be read from the stream. An internal
* counter keeps track of the next byte to
* be supplied by the {@code read} method.
* <p>
* Closing a {@code ByteArrayImageInputStream} has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an {@code IOException}.
*
* @author Werner Randelshofer, Hausmatt 10, CH-6405 Immensee
* @version $Id: ByteArrayImageInputStream.java 134 2011-12-02 16:23:00Z werner $
*/
public class ByteArrayImageInputStream extends ImageInputStreamImpl2 {
/**
* An array of bytes that was provided
* by the creator of the stream. Elements <code>buf[0]</code>
* through <code>buf[count-1]</code> are the
* only bytes that can ever be read from the
* stream; element <code>buf[streamPos]</code> is
* the next byte to be read.
*/
protected byte buf[];
/**
* The index one greater than the last valid character in the input
* stream buffer.
* This value should always be nonnegative
* and not larger than the length of <code>buf</code>.
* It is one greater than the position of
* the last byte within <code>buf</code> that
* can ever be read from the input stream buffer.
*/
protected int count;
/** The offset to the start of the array. */
private final int arrayOffset;
public ByteArrayImageInputStream(byte[] buf) {
this(buf, ByteOrder.BIG_ENDIAN);
}
public ByteArrayImageInputStream(byte[] buf, ByteOrder byteOrder) {
this(buf, 0, buf.length, byteOrder);
}
public ByteArrayImageInputStream(byte[] buf, int offset, int length, ByteOrder byteOrder) {
this.buf = buf;
this.streamPos = offset;
this.count = Math.min(offset + length, buf.length);
this.arrayOffset = offset;
this.byteOrder = byteOrder;
}
/**
* Reads the next byte of data from this input stream. The value
* byte is returned as an <code>int</code> in the range
* <code>0</code> to <code>255</code>. If no byte is available
* because the end of the stream has been reached, the value
* <code>-1</code> is returned.
* <p>
* This <code>read</code> method
* cannot block.
*
* @return the next byte of data, or <code>-1</code> if the end of the
* stream has been reached.
*/
@Override
public synchronized int read() {
flushBits();
return (streamPos < count) ? (buf[(int)(streamPos++)] & 0xff) : -1;
}
/**
* Reads up to <code>len</code> bytes of data into an array of bytes
* from this input stream.
* If <code>streamPos</code> equals <code>count</code>,
* then <code>-1</code> is returned to indicate
* end of file. Otherwise, the number <code>k</code>
* of bytes read is equal to the smaller of
* <code>len</code> and <code>count-streamPos</code>.
* If <code>k</code> is positive, then bytes
* <code>buf[streamPos]</code> through <code>buf[streamPos+k-1]</code>
* are copied into <code>b[off]</code> through
* <code>b[off+k-1]</code> in the manner performed
* by <code>System.arraycopy</code>. The
* value <code>k</code> is added into <code>streamPos</code>
* and <code>k</code> is returned.
* <p>
* This <code>read</code> method cannot block.
*
* @param b the buffer into which the data is read.
* @param off the start offset in the destination array <code>b</code>
* @param len the maximum number of bytes read.
* @return the total number of bytes read into the buffer, or
* <code>-1</code> if there is no more data because the end of
* the stream has been reached.
* @exception NullPointerException If <code>b</code> is <code>null</code>.
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
* <code>len</code> is negative, or <code>len</code> is greater than
* <code>b.length - off</code>
*/
@Override
public synchronized int read(byte b[], int off, int len) {
flushBits();
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
}
if (streamPos >= count) {
return -1;
}
if (streamPos + len > count) {
len = (int)(count - streamPos);
}
if (len <= 0) {
return 0;
}
System.arraycopy(buf, (int)streamPos, b, off, len);
streamPos += len;
return len;
}
/**
* Skips <code>n</code> bytes of input from this input stream. Fewer
* bytes might be skipped if the end of the input stream is reached.
* The actual number <code>k</code>
* of bytes to be skipped is equal to the smaller
* of <code>n</code> and <code>count-streamPos</code>.
* The value <code>k</code> is added into <code>streamPos</code>
* and <code>k</code> is returned.
*
* @param n the number of bytes to be skipped.
* @return the actual number of bytes skipped.
*/
public synchronized long skip(long n) {
if (streamPos + n > count) {
n = count - streamPos;
}
if (n < 0) {
return 0;
}
streamPos += n;
return n;
}
/**
* Returns the number of remaining bytes that can be read (or skipped over)
* from this input stream.
* <p>
* The value returned is <code>count - streamPos</code>,
* which is the number of bytes remaining to be read from the input buffer.
*
* @return the number of remaining bytes that can be read (or skipped
* over) from this input stream without blocking.
*/
public synchronized int available() {
return (int)(count - streamPos);
}
/**
* Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an <tt>IOException</tt>.
* <p>
*/
@Override
public void close() {
// does nothing!!
}
@Override
public long getStreamPosition() throws IOException {
checkClosed();
return streamPos-arrayOffset;
}
@Override
public void seek(long pos) throws IOException {
checkClosed();
flushBits();
// This test also covers pos < 0
if (pos < flushedPos) {
throw new IndexOutOfBoundsException("pos < flushedPos!");
}
this.streamPos = pos+arrayOffset;
}
private void flushBits() {
bitOffset=0;
}
@Override
public long length() {
return count-arrayOffset;
}
}