View Javadoc
1   /*
2    *  Licensed under the Apache License, Version 2.0 (the "License");
3    *  you may not use this file except in compliance with the License.
4    *  You may obtain a copy of the License at
5    *
6    *       http://www.apache.org/licenses/LICENSE-2.0
7    *
8    *  Unless required by applicable law or agreed to in writing, software
9    *  distributed under the License is distributed on an "AS IS" BASIS,
10   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   *  See the License for the specific language governing permissions and
12   *  limitations under the License.
13   *  under the License.
14   */
15  
16  package org.apache.commons.imaging.formats.jpeg.decoder;
17  
18  import java.util.Arrays;
19  
20  import org.apache.commons.imaging.ImagingException;
21  import org.apache.commons.imaging.formats.jpeg.JpegConstants;
22  
23  final class JpegInputStream {
24      static final int SHALLOW_SIZE = 32;
25      // Figure F.18, F.2.2.5, page 111 of ITU-T T.81
26      private final int[] interval;
27      // next position in the array to read
28      private int nextPos;
29      private int cnt;
30      private int b;
31  
32      JpegInputStream(final int[] interval) {
33          this.interval = Arrays.copyOf(interval, interval.length);
34          this.nextPos = 0;
35      }
36  
37      /**
38       * Returns {@code true} as long there are unread fields available, else {@code false}
39       *
40       * @return {@code true} as long there are unread fields available, else {@code false}
41       */
42      public boolean hasNext() {
43          return nextPos < this.interval.length;
44      }
45  
46      public int nextBit() throws ImagingException {
47          if (cnt == 0) {
48              b = this.read();
49              if (b < 0) {
50                  throw new ImagingException("Premature End of File");
51              }
52              cnt = 8;
53              if (b == 0xff) {
54                  final int b2 = this.read();
55                  if (b2 < 0) {
56                      throw new ImagingException("Premature End of File");
57                  }
58                  if (b2 != 0) {
59                      if (b2 == (0xff & JpegConstants.DNL_MARKER)) {
60                          throw new ImagingException("DNL not yet supported");
61                      }
62                      throw new ImagingException("Invalid marker found " + "in entropy data: 0xFF " + Integer.toHexString(b2));
63                  }
64              }
65          }
66          final int bit = b >> 7 & 0x1;
67          cnt--;
68          b <<= 1;
69          return bit;
70      }
71  
72      /**
73       * Returns the value from current field (as {@code InputStream.read()} would do) and set the position of the pointer to the next field to read.
74       *
75       * @return the value from current field (as {@code InputStream.read()} would do).
76       * @throws IllegalStateException if the stream hasn't any other value.
77       */
78      int read() {
79          if (!this.hasNext()) {
80              throw new IllegalStateException("This stream hasn't any other value, all values were already read.");
81          }
82          final int value = this.interval[nextPos];
83          this.nextPos++;
84          return value;
85      }
86  }