/Users/lyon/j4p/src/face/PPMFile.java

1    package face; 
2     
3     
4    import java.io.*; 
5     
6    /** 
7     * PPM File reader/writer. Works with type 2,4-6. 
8     * 
9     * 
10    * 
11    */ 
12   public class PPMFile implements ImageFileFormat { 
13    
14    
15       private byte bytes[] = null;      // bytes which make up binary PPM image 
16       private double doubles[] = null; 
17       private String filename = null;     // filename for PPM image 
18       private int height = 0; 
19       private int width = 0; 
20    
21       /** 
22        * Read the PPM File. 
23        * 
24        * @throws   java.io.FileNotFoundException   if the directory/image specified is wrong 
25        * @throws   java.io.IOException  if there are problems reading the file. 
26        */ 
27       public PPMFile(String filename) throws FileNotFoundException, IOException { 
28           this.filename = filename; 
29           readImage(); 
30       } 
31    
32       /** 
33        * Get the height of the PPM image. 
34        * 
35        * @return the height of the image. 
36        */ 
37       public int getHeight() { 
38           return height; 
39       } 
40    
41       /** 
42        * Get the width of the PPM image. 
43        * 
44        * @return  the width of the image. 
45        */ 
46       public int getWidth() { 
47           return width; 
48       } 
49    
50       /** 
51        * Get the data as byte array. Data is of any type that 
52        * has been read from the file (usually 8bit RGB) 
53        * 
54        * @return  The data of the image. 
55        */ 
56       public byte[] getBytes() { 
57           return bytes; 
58       } 
59    
60       /** 
61        * Get the data as double array. Data is of any type that 
62        * has been read from the file (usually 8bit RGB put into an 64bit double) 
63        * 
64        * @return  The data of the image. 
65        */ 
66       public double[] getDouble() { 
67           return doubles; 
68       } 
69    
70       /** 
71        * Write to <code&gt;fn</code&gt; file the <code&gt;data</code&gt; using the 
72        * <code&gt;width, height</code&gt; variables. Data is assumed to be 8bit RGB. 
73        * 
74        * @throws   java.io.FileNotFoundException   if the directory/image specified is wrong 
75        * @throws   java.io.IOException  if there are problems reading the file. 
76        */ 
77       public static void writeImage(String fn, byte[] data, int width, int height) 
78               throws FileNotFoundException, IOException { 
79    
80           if (data != null) { 
81    
82               FileOutputStream fos = new FileOutputStream(fn); 
83               fos.write(new String("P6\n").getBytes()); 
84               fos.write(new String(width + " " + height + "\n").getBytes()); 
85               fos.write(new String("255\n").getBytes()); 
86               System.out.println(data.length); 
87               fos.write(data); 
88               fos.close(); 
89           } 
90       } 
91    
92       /** 
93        * Read the image from the specified file. 
94        * 
95        * @throws  java.io.FileNotFoundException pretty obvious 
96        * @throws  java.io.IOException filesystem related problems 
97        * @throws  java.lang.NumberFormatException the input data is incorrect 
98        */ 
99       private void readImage() throws FileNotFoundException, IOException, NumberFormatException { 
100   
101          // read PPM format image 
102          bytes = null; 
103          char buffer;                   // character in PPM header 
104          String id = new String();      // PPM magic number ("P6") 
105          String dim = new String();     // image dimension as a string 
106          int count = 0; 
107          File f = new File(filename); 
108          FileInputStream isr = new FileInputStream(f); 
109          boolean weird = false; 
110   
111          do { 
112              buffer = (char) isr.read(); 
113              id = id + buffer; 
114              count++; 
115          } while (buffer != '\n' && buffer != ' '); 
116   
117          if (id.charAt(0) == 'P') { 
118   
119   
120              buffer = (char) isr.read(); 
121              count++; 
122              if (buffer == '#') { 
123                  do { 
124                      buffer = (char) isr.read(); 
125                      count++; 
126                  } while (buffer != '\n'); 
127                  count++; 
128                  buffer = (char) isr.read(); 
129              } 
130              // second header line is "width height\n" 
131              do { 
132                  dim = dim + buffer; 
133                  buffer = (char) isr.read(); 
134                  count++; 
135              } while (buffer != ' ' && buffer != '\n'); 
136   
137              width = Integer.parseInt(dim); 
138              //System.out.print(width); 
139              //System.out.flush(); 
140              dim = new String(); 
141              buffer = (char) isr.read(); 
142              count++; 
143              do { 
144                  dim = dim + buffer; 
145                  buffer = (char) isr.read(); 
146                  count++; 
147              } while (buffer != ' ' && buffer != '\n'); 
148              height = Integer.parseInt(dim); 
149              //System.out.println(" X " + height + " pixels."); 
150              do {                          // third header line is max RGB value, e.g., "255\n" 
151                  buffer = (char) isr.read(); 
152                  count++; 
153              } while (buffer != ' ' && buffer != '\n'); 
154   
155              //System.out.print("Reading image..."); 
156              //System.out.flush(); 
157   
158              // remainder of file is width*height*3 bytes (red/green/blue triples) 
159   
160              bytes = new byte[height * width]; 
161              doubles = new double[height * width]; 
162   
163              /* 
164               Check for weird stuff 
165              */ 
166              if ((height * width + count * 2) < f.length()) 
167                  weird = true; 
168   
169              if ((id.charAt(1) == '5') || (id.charAt(1) == '6')) { 
170                  if (!weird) 
171                      isr.read(bytes, 0, height * width); 
172                  // Now read in as double 
173                  else { 
174                      // There are nine bytes per RGB-tuple. Good for 32-bit color, 
175                      // not for us. 
176                      int v = 0; 
177                      for (int i = 0; i < height * width; i++) { 
178                          v = isr.read(); 
179                          v = v + isr.read(); 
180                          v = v + isr.read(); 
181                          v = v / 3; 
182                          bytes[i] = (byte) (v & 0xFF); 
183                      } 
184                  } 
185              } 
186              if (id.charAt(1) == '2') { 
187                  int i = 0; 
188                  for (i = 0; i < width * height; i++) { 
189                      dim = new String(); 
190                      do { 
191                          buffer = (char) isr.read(); 
192                          if (buffer != ' ' && buffer != '\n') 
193                              dim = dim + buffer; 
194                      } while (buffer != ' ' && buffer != '\n'); 
195                      bytes[i] = (byte) (Integer.parseInt(dim) & 0xFF); 
196   
197                  } 
198              } 
199              // Convert to double. 
200              for (int i = 0; i < height * width; i++) 
201                  doubles[i] = (double) (bytes[i] & 0xFF); 
202   
203              isr.close(); 
204          } else { 
205              width = height = 0; 
206              doubles = new double[0]; 
207              bytes = new byte[0]; 
208              throw new NumberFormatException("Wrong header information!"); 
209          } 
210      } 
211  } 
212