public static BufferedImage loadPPM( InputStream inputStream , BufferedImage storage ) throws IOException {
		DataInputStream in = new DataInputStream(inputStream);

		readLine(in);
		String line = readLine(in);
		while( line.charAt(0) == '#')
			line = readLine(in);
		String s[] = line.split(" ");
		int w = Integer.parseInt(s[0]);
		int h = Integer.parseInt(s[1]);
		readLine(in);

		if( storage == null || storage.getWidth() != w || storage.getHeight() != h )
			storage = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB );

		int length = w*h*3;
		byte[] data = new byte[length];

		read(in,data,length);

		boolean useFailSafe = storage.getType() != BufferedImage.TYPE_INT_RGB;
		// try using the internal array for better performance
		if( storage.getRaster().getDataBuffer().getDataType() == DataBuffer.TYPE_INT ) {
			int rgb[] =  ((DataBufferInt)storage.getRaster().getDataBuffer()).getData();

			int indexIn = 0;
			int indexOut = 0;
			for( int y = 0; y < h; y++ ) {
				for( int x = 0; x < w; x++ ) {
					rgb[indexOut++] = ((data[indexIn++] & 0xFF) << 16) |
							((data[indexIn++] & 0xFF) << 8) | (data[indexIn++] & 0xFF);
				}
			}
		}

		if( useFailSafe ) {
			// use the slow setRGB() function
			int indexIn = 0;
			for( int y = 0; y < h; y++ ) {
				for( int x = 0; x < w; x++ ) {
					storage.setRGB(x, y, ((data[indexIn++] & 0xFF) << 16) |
							((data[indexIn++] & 0xFF) << 8) | (data[indexIn++] & 0xFF));
				}
			}
		}

		return storage;
	}
public static BufferedImage loadPPM ( InputStream inputStream , BufferedImage storage ) throws IOException { DataInputStream in = new DataInputStream ( inputStream ) ; readLine ( in ) ; String line = readLine ( in ) ; while ( line . charAt ( 0 ) == '#' ) line = readLine ( in ) ; String s [ ] = line . split ( " " ) ; int w = Integer . parseInt ( s [ 0 ] ) ; int h = Integer . parseInt ( s [ 1 ] ) ; readLine ( in ) ; if ( storage == null || storage . getWidth ( ) != w || storage . getHeight ( ) != h ) storage = new BufferedImage ( w , h , BufferedImage . TYPE_INT_RGB ) ; int length = w * h * 3 ; byte [ ] data = new byte [ length ] ; read ( in , data , length ) ; boolean useFailSafe = storage . getType ( ) != BufferedImage . TYPE_INT_RGB ; if ( storage . getRaster ( ) . getDataBuffer ( ) . getDataType ( ) == DataBuffer . TYPE_INT ) { int rgb [ ] = ( ( DataBufferInt ) storage . getRaster ( ) . getDataBuffer ( ) ) . getData ( ) ; int indexIn = 0 ; int indexOut = 0 ; for ( int y = 0 ; y < h ; y ++ ) { for ( int x = 0 ; x < w ; x ++ ) { rgb [ indexOut ++ ] = ( ( data [ indexIn ++ ] & 0xFF ) << 16 ) | ( ( data [ indexIn ++ ] & 0xFF ) << 8 ) | ( data [ indexIn ++ ] & 0xFF ) ; } } } if ( useFailSafe ) { int indexIn = 0 ; for ( int y = 0 ; y < h ; y ++ ) { for ( int x = 0 ; x < w ; x ++ ) { storage . setRGB ( x , y , ( ( data [ indexIn ++ ] & 0xFF ) << 16 ) | ( ( data [ indexIn ++ ] & 0xFF ) << 8 ) | ( data [ indexIn ++ ] & 0xFF ) ) ; } } } return storage ; }
Loads a PPM image from an {@link InputStream}.

@param inputStream InputStream for PPM image
@param storage (Optional) Storage for output image.  Must be the width and height of the image being read.
Better performance of type BufferedImage.TYPE_INT_RGB.  If null or width/height incorrect a new image
will be declared.
@return The read in image
@throws IOException Thrown if there is a problem reading the image