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  import java.nio.charset.StandardCharsets;
31  
32  /**
33   * <a href="http://en.wikipedia.org/wiki/Portable_pixmap">PBM</a> images reader.
34   */
35  class PBMReader
36  {
37      static final int TYPE_PBM = 1;
38  
39      static final int TYPE_PGM = 2;
40  
41      static final int TYPE_PPM = 3;
42  
43      private static final String BAD_FILE_FORMAT = "bad file format";
44  
45      private static final String UNSUPPORTED_TYPE = "unsupported file type";
46  
47      private static final String UNSUPPORTED_FORMAT = "unsupported data format";
48  
49      private static final String UNSUPPORTED_DEPTH = "unsupported color depth";
50  
51      protected int type;
52  
53      protected boolean binary;
54  
55      protected int width;
56  
57      protected int height;
58  
59      protected int maxValue;
60  
61      private int bytesPerLine;
62  
63      private InputStream stream;
64  
65      PBMReader( String fileName )
66          throws Exception
67      {
68          HeaderReader header = new HeaderReader();
69  
70          int length = header.read( fileName );
71  
72          if ( type != TYPE_PPM )
73          {
74              throw new Exception( UNSUPPORTED_TYPE );
75          }
76  
77          if ( !binary )
78          {
79              throw new Exception( UNSUPPORTED_FORMAT );
80          }
81  
82          if ( maxValue > 255 )
83          {
84              throw new Exception( UNSUPPORTED_DEPTH );
85          }
86  
87          switch ( type )
88          {
89              case TYPE_PBM:
90                  bytesPerLine = ( width + 7 ) / 8;
91                  break;
92              case TYPE_PGM:
93                  bytesPerLine = width;
94                  break;
95              case TYPE_PPM:
96                  bytesPerLine = 3 * width;
97                  break;
98              default:
99          }
100 
101         stream = new BufferedInputStream( new FileInputStream( fileName ) );
102 
103         skip( length );
104     }
105 
106     int type()
107     {
108         return type;
109     }
110 
111     int width()
112     {
113         return width;
114     }
115 
116     int height()
117     {
118         return height;
119     }
120 
121     int maxValue()
122     {
123         return maxValue;
124     }
125 
126     int bytesPerLine()
127     {
128         return bytesPerLine;
129     }
130 
131     long skip( long count )
132         throws IOException
133     {
134         long skipped = stream.skip( count );
135 
136         if ( skipped < count )
137         {
138             byte[] b = new byte[512];
139             while ( skipped < count )
140             {
141                 int len = (int) Math.min( b.length, ( count - skipped ) );
142                 int n = stream.read( b, 0, len );
143                 if ( n < 0 )
144                 {
145                     break; // end of file
146                 }
147                 skipped += n;
148             }
149         }
150 
151         return skipped;
152     }
153 
154     int read( byte[] b, int off, int len )
155         throws IOException
156     {
157         int count = 0;
158         while ( count < len )
159         {
160             int n = stream.read( b, off + count, len - count );
161             if ( n < 0 )
162             {
163                 break; // end of file
164             }
165             count += n;
166         }
167         return count;
168     }
169 
170     // -----------------------------------------------------------------------
171 
172     class HeaderReader
173     {
174 
175         private Reader reader;
176 
177         private int offset;
178 
179         int read( String fileName )
180             throws Exception
181         {
182             String field;
183 
184             reader = new BufferedReader( new InputStreamReader(
185                     new FileInputStream( fileName ), StandardCharsets.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 }