/* * This file is part of Mapyrus, software for plotting maps. * Copyright (C) 2003 - 2011 Simon Chenery. * * Mapyrus is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Mapyrus 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Mapyrus; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * =========================================================================== * * Reusing this in freelibrary-djatoka to get rid of current JAI dependency; I * also made a few minor changes (changed exceptions, parameters passed, etc.) * * Kevin S. Clarke <ksclarke@gmail.com> */ package info.freelibrary.djatoka.io; import gov.lanl.adore.djatoka.io.FormatIOException; import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /* * Holds an image read from a Netpbm PPM and PGM format image files. */ public class PNMImage { private BufferedImage m_image; /** * Read Netpbm PNM image from file. * * @param filename * name of file. */ public PNMImage(String filename) throws FormatIOException, IOException { this(new FileInputStream(filename)); } /** * Read Netpbm PNM image from open stream. * * @param stream * open stream to read from. * @param filename * name of file. */ public PNMImage(InputStream aInputStream) throws FormatIOException, IOException { DataInputStream stream = new DataInputStream(new BufferedInputStream( aInputStream)); try { /* * Check for 'P5' or 'P6' magic number in file. */ int magic1 = stream.read(); int magic2 = stream.read(); boolean isGreyscale; boolean isBitmap; if (magic1 == 'P' && magic2 == '6') { isGreyscale = isBitmap = false; } else if (magic1 == 'P' && magic2 == '5') { isGreyscale = true; isBitmap = false; } else if (magic1 == 'P' && magic2 == '4') { isBitmap = true; isGreyscale = false; } else { throw new FormatIOException("Bad PPM magic number: " + magic1 + magic2); } /* * Read image header. */ int width = readNumber(stream); int height = readNumber(stream); int maxValue = 1; if (!isBitmap) maxValue = readNumber(stream); int nBytes = (maxValue < 256) ? 1 : 2; /* * Read pixel values into image. */ m_image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); int nextByte = 0; for (int y = 0; y < height; y++) { int bitMask = 0; for (int x = 0; x < width; x++) { int r, g, b, pixel; if (nBytes == 1) { if (isBitmap) { /* * Extract pixel from next bit. */ if (bitMask == 0) { nextByte = stream.read(); bitMask = 128; } r = g = b = (((nextByte & bitMask) != 0) ? 0 : 255); bitMask >>= 1; } else if (isGreyscale) { r = g = b = stream.read(); } else { r = stream.read(); g = stream.read(); b = stream.read(); } } else { if (isGreyscale) { r = g = b = stream.readShort(); } else { r = stream.readShort(); g = stream.readShort(); b = stream.readShort(); } } pixel = (r << 16) | (g << 8) | b; m_image.setRGB(x, y, pixel); } } } finally { try { stream.close(); } catch (IOException e) { } } } /** * Read decimal number from stream. * * @param stream * stream to read from. * @return number read from stream. */ private int readNumber(InputStream stream) throws IOException { int retval = 0; int c = stream.read(); boolean inComment = (c == '#'); while (c != -1 && (inComment || Character.isWhitespace((char) c))) { c = stream.read(); if (c == '#') inComment = true; else if (inComment && (c == '\r' || c == '\n')) inComment = false; } while (c >= '0' && c <= '9') { retval = retval * 10 + (c - '0'); c = stream.read(); } return (retval); } /** * Get Netpbm PNM image as buffered image. * * @return image. */ public BufferedImage getBufferedImage() { return (m_image); } /** * Write an image to a Netpbm PPM format file. * * @param image * image to write * @param stream * output stream to write image to. */ public static void write(BufferedImage image, OutputStream stream) throws IOException { /* * Write file header. */ int imageWidth = image.getWidth(); int imageHeight = image.getHeight(); stream.write('P'); stream.write('6'); stream.write('\n'); stream.write(Integer.toString(imageWidth).getBytes()); stream.write(' '); stream.write(Integer.toString(imageHeight).getBytes()); stream.write('\n'); stream.write(Integer.toString(255).getBytes()); stream.write('\n'); /* * Write each row of pixels. */ for (int y = 0; y < imageHeight; y++) { for (int x = 0; x < imageWidth; x++) { int pixel = image.getRGB(x, y); int b = (pixel & 0xff); int g = ((pixel >> 8) & 0xff); int r = ((pixel >> 16) & 0xff); stream.write(r); stream.write(g); stream.write(b); } } stream.flush(); } }