View Javadoc
1   package org.apache.maven.doxia.module.rtf;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.BufferedInputStream;
23  import java.io.BufferedReader;
24  import java.io.EOFException;
25  import java.io.FileInputStream;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.io.InputStreamReader;
29  import java.io.Reader;
30  
31  /**
32   * <a href="http://en.wikipedia.org/wiki/Portable_pixmap">PBM</a> images reader.
33   *
34   * @version $Id: PBMReader.java 1633964 2014-10-23 22:01:01Z hboutemy $
35   */
36  class PBMReader
37  {
38      static final int TYPE_PBM = 1;
39  
40      static final int TYPE_PGM = 2;
41  
42      static final int TYPE_PPM = 3;
43  
44      private static final String BAD_FILE_FORMAT = "bad file format";
45  
46      private static final String UNSUPPORTED_TYPE = "unsupported file type";
47  
48      private static final String UNSUPPORTED_FORMAT = "unsupported data format";
49  
50      private static final String UNSUPPORTED_DEPTH = "unsupported color depth";
51  
52      protected int type;
53  
54      protected boolean binary;
55  
56      protected int width;
57  
58      protected int height;
59  
60      protected int maxValue;
61  
62      private int bytesPerLine;
63  
64      private InputStream stream;
65  
66      PBMReader( String fileName )
67          throws Exception
68      {
69          HeaderReader header = new HeaderReader();
70  
71          int length = header.read( fileName );
72  
73          if ( type != TYPE_PPM )
74          {
75              throw new Exception( UNSUPPORTED_TYPE );
76          }
77  
78          if ( !binary )
79          {
80              throw new Exception( UNSUPPORTED_FORMAT );
81          }
82  
83          if ( maxValue > 255 )
84          {
85              throw new Exception( UNSUPPORTED_DEPTH );
86          }
87  
88          switch ( type )
89          {
90              case TYPE_PBM:
91                  bytesPerLine = ( width + 7 ) / 8;
92                  break;
93              case TYPE_PGM:
94                  bytesPerLine = width;
95                  break;
96              case TYPE_PPM:
97                  bytesPerLine = 3 * width;
98                  break;
99              default:
100         }
101 
102         stream = new BufferedInputStream( new FileInputStream( fileName ) );
103 
104         skip( length );
105     }
106 
107     int type()
108     {
109         return type;
110     }
111 
112     int width()
113     {
114         return width;
115     }
116 
117     int height()
118     {
119         return height;
120     }
121 
122     int maxValue()
123     {
124         return maxValue;
125     }
126 
127     int bytesPerLine()
128     {
129         return bytesPerLine;
130     }
131 
132     long skip( long count )
133         throws IOException
134     {
135         long skipped = stream.skip( count );
136 
137         if ( skipped < count )
138         {
139             byte[] b = new byte[512];
140             while ( skipped < count )
141             {
142                 int len = (int) Math.min( b.length, ( count - skipped ) );
143                 int n = stream.read( b, 0, len );
144                 if ( n < 0 )
145                 {
146                     break; // end of file
147                 }
148                 skipped += n;
149             }
150         }
151 
152         return skipped;
153     }
154 
155     int read( byte[] b, int off, int len )
156         throws IOException
157     {
158         int count = 0;
159         while ( count < len )
160         {
161             int n = stream.read( b, off + count, len - count );
162             if ( n < 0 )
163             {
164                 break; // end of file
165             }
166             count += n;
167         }
168         return count;
169     }
170 
171     // -----------------------------------------------------------------------
172 
173     class HeaderReader
174     {
175 
176         private Reader reader;
177 
178         private int offset;
179 
180         int read( String fileName )
181             throws Exception
182         {
183             String field;
184 
185             reader = new BufferedReader( new InputStreamReader( new FileInputStream( fileName ), "US-ASCII" ) );
186             offset = 0;
187 
188             field = getField();
189             if ( field.length() != 2 || field.charAt( 0 ) != 'P' )
190             {
191                 reader.close();
192                 throw new Exception( BAD_FILE_FORMAT );
193             }
194             switch ( field.charAt( 1 ) )
195             {
196                 case '1':
197                 case '4':
198                     type = TYPE_PBM;
199                     break;
200                 case '2':
201                 case '5':
202                     type = TYPE_PGM;
203                     break;
204                 case '3':
205                 case '6':
206                     type = TYPE_PPM;
207                     break;
208                 default:
209                     reader.close();
210                     throw new Exception( BAD_FILE_FORMAT );
211             }
212             if ( field.charAt( 1 ) > '3' )
213             {
214                 binary = true;
215             }
216             else
217             {
218                 binary = false;
219             }
220 
221             try
222             {
223                 width = Integer.parseInt( getField() );
224                 height = Integer.parseInt( getField() );
225                 if ( type == TYPE_PBM )
226                 {
227                     maxValue = 1;
228                 }
229                 else
230                 {
231                     maxValue = Integer.parseInt( getField() );
232                 }
233             }
234             catch ( NumberFormatException e )
235             {
236                 reader.close();
237                 throw new Exception( BAD_FILE_FORMAT );
238             }
239 
240             reader.close();
241 
242             return offset;
243         }
244 
245         private String getField()
246             throws IOException
247         {
248             char c;
249             StringBuilder field = new StringBuilder();
250 
251             try
252             {
253                 do
254                 {
255                     while ( ( c = getChar() ) == '#' )
256                     {
257                         skipComment();
258                     }
259                 }
260                 while ( Character.isWhitespace( c ) );
261 
262                 field.append( c );
263 
264                 while ( !Character.isWhitespace( c = getChar() ) )
265                 {
266                     if ( c == '#' )
267                     {
268                         skipComment();
269                         break;
270                     }
271                     field.append( c );
272                 }
273             }
274             catch ( EOFException ignore )
275             {
276                 // nop
277             }
278 
279             return field.toString();
280         }
281 
282         private char getChar()
283             throws IOException, EOFException
284         {
285             int c = reader.read();
286             if ( c < 0 )
287             {
288                 throw new EOFException();
289             }
290             offset += 1;
291             return (char) c;
292         }
293 
294         private void skipComment()
295             throws IOException
296         {
297             try
298             {
299                 while ( getChar() != '\n' )
300                 {
301                     // nop
302                 }
303             }
304             catch ( EOFException ignore )
305             {
306                 // nop
307             }
308         }
309     }
310 }