/* * This file is part of Caliph & Emir. * * Caliph & Emir is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Caliph & Emir is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Caliph & Emir; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright statement: * -------------------- * (c) 2002-2006 by Mathias Lux (mathias@juggle.at) * http://www.juggle.at, http://caliph-emir.sourceforge.net */ package at.lux.imaging; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.IOException; import java.io.InputStream; /** * Class for decoding a ppm image. Instructions can be found at * <a href="http://netpbm.sourceforge.net/doc/ppm.html"> * http://netpbm.sourceforge.net/doc/ppm.html</a> <br/> * <p/> * Please note that the "plain format" P3 is not supported! * * @author Mathias Lux, mathias@juggle.at * Date: 03.11.2006 * Time: 09:07:42 */ public class PpmReader { public static BufferedImage read(InputStream in) throws IOException { String magicNumber = null; String comment = null; int height = -1, width = -1, maxVal = -1; magicNumber = getMagicNumer(in); width = getNumber(in); height = getNumber(in); maxVal = getNumber(in); // System.out.println("magicNumber = " + magicNumber); // System.out.println("width = " + width); // System.out.println("height = " + height); // System.out.println("maxVal = " + maxVal); if (maxVal > 255 || !magicNumber.equals("P6")) throw new IOException("Could not decode image!"); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); WritableRaster r = image.getRaster(); int[] rgb = new int[3]; int count = 0; if (maxVal < 256) decode255(count, width, height, in, maxVal, rgb, r); else decode65535(count, width, height, in, maxVal, rgb, r); return image; } private static void decode255(int count, int width, int height, InputStream in, int maxVal, int[] rgb, WritableRaster r) throws IOException { int val; int numpixel; while (count < width * height * 3) { while ((val = in.read()) > -1) { // support for less 255 maxVal: if (maxVal < 255) val = val * 255 / maxVal; rgb[count % 3] = val; if (count % 3 == 2) { numpixel = (count / 3); try { r.setPixel(numpixel % width, numpixel / width, rgb); // System.out.println("Set pixel @ (" + numpixel % width + "," + numpixel / width + ")"); } catch (Exception e) { System.err.println("Tried to set pixel @ (" + numpixel % width + "," + numpixel / width + ")"); e.printStackTrace(); throw new IOException("Could not decode image!"); } } count++; } } } private static void decode65535(int count, int width, int height, InputStream in, int maxVal, int[] rgb, WritableRaster r) throws IOException { int val, tmpVal; int numpixel; while (count < width * height * 3) { while ((val = in.read()) > -1) { tmpVal = val * 255; tmpVal += in.read(); // support for less 65535 maxVal: if (maxVal < 65535) tmpVal = tmpVal * 65535 / maxVal; rgb[count % 3] = tmpVal; if (count % 3 == 2) { numpixel = (count / 3); try { r.setPixel(numpixel % width, numpixel / width, rgb); // System.out.println("Set pixel @ (" + numpixel % width + "," + numpixel / width + ")"); } catch (Exception e) { System.err.println("Tried to set pixel @ (" + numpixel % width + "," + numpixel / width + ")"); e.printStackTrace(); throw new IOException("Could not decode image!"); } } count++; } } } private static int getNumber(InputStream in) throws IOException { StringBuilder sb = new StringBuilder(64); int val; char letter, lastLetter = '\n'; while ((val = in.read()) > -1) { letter = (char) val; if (lastLetter == '\n' && letter == '#') { skipComment(in); } else if (!Character.isWhitespace(letter)) { sb.append(letter); } else if (Character.isWhitespace(lastLetter)) { // skip .. } else { return Integer.parseInt(sb.toString()); } lastLetter = letter; } return 0; } private static String getMagicNumer(InputStream in) throws IOException { StringBuilder sb = new StringBuilder(64); int val; char letter, lastLetter = '0'; while ((val = in.read()) > -1) { letter = (char) val; if (lastLetter == 'P') { sb.append(lastLetter); sb.append(letter); return sb.toString(); } else if (lastLetter == '\n' && letter == '#') { skipComment(in); } lastLetter = letter; } return null; } private static void skipComment(InputStream in) throws IOException { StringBuilder sb = new StringBuilder(64); int val; char letter; sb.append('#'); while ((val = in.read()) > -1) { letter = (char) val; if (letter != '\n') { sb.append(letter); } else { // System.out.println(sb.toString()); return; } } } }