/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>fn</code> file the <code>data</code> using the
72 * <code>width, height</code> 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