/* BEGIN_HEADER                                              Java TreeView
*
* $Author: alokito $
* $RCSfile: PpmWriter.java,v $
* $Revision: 1.4 $
* $Date: 2004-12-21 03:28:13 $
* $Name:  $
*
* This file is part of Java TreeView
* Copyright (C) 2001-2003 Alok Saldanha, All Rights Reserved. Modified by Alex Segal 2004/08/13. Modifications Copyright (C) Lawrence Berkeley Lab.
*
* This software is provided under the GNU GPL Version 2. In particular, 
*
* 1) If you modify a source file, make a comment in it containing your name and the date.
* 2) If you distribute a modified version, you must do it under the GPL 2.
* 3) Developers are encouraged but not required to notify the Java TreeView maintainers at alok@genome.stanford.edu when they make a useful addition. It would be nice if significant contributions could be merged into the main distribution.
*
* A full copy of the license can be found in gpl.txt or online at
* http://www.gnu.org/licenses/gpl.txt
*
* END_HEADER 
*/
package edu.stanford.genetics.treeview;

import java.awt.Image;
import java.awt.image.PixelGrabber;
import java.io.IOException;
import java.io.OutputStream;

/**
* This is a completely generic and self sufficient static class that writes images to PPM format files.
*/
public class PpmWriter {
	
	public static void writePpm(Image image, OutputStream out) throws java.io.IOException {
		int pixels[][] = getPixels(image);
		int width = pixels.length;
		int height = pixels[0].length;
		//# Each PPM image consists of the following: 
		//# 1) A "magic number" for identifying the file type. A ppm image's magic number is the two characters "P6". 
		out.write(("P6").getBytes());
		//# 2) Whitespace (blanks, TABs, CRs, LFs). 
		out.write(("\n").getBytes());
		//	# 3) A width, formatted as ASCII characters in decimal. 
		out.write(("" + width).getBytes());
		//# 4) Whitespace. 
		out.write(("\n").getBytes());
		//# 5) A height, again in ASCII decimal. 
		out.write(("" + height).getBytes());
		//# 6) Whitespace. 
		out.write(("\n").getBytes());
		//# 7) The maximum color value (Maxval), again in ASCII decimal.  Must be less than 65536. 
		out.write(("255").getBytes());
		//# 8) Newline or other single whitespace character. 
		out.write(("\n").getBytes());
		//# 9) A raster of Height rows, in order from top to bottom.  Each row consists of Width pixels, in order from left # to right.  Each pixel is a triplet of red, green, and blue samples, in that order.  Each sample is represented in pure binary by either 1 or 2 bytes.  If the Maxval is less than 256, it is 1 byte.  Otherwise, it is 2 bytes.  The most significant byte is first. 
		for (int row = 0; row < height; row++) {
			for (int col = 0; col < width; col++) {
				printColor(out, pixels[col][row]);
			}
		}
	}
	public static void printColor(OutputStream out, int val) throws java.io.IOException {
		int blue = val;
		int green = val >> 8;
		int red = val >> 16;
		
		
		out.write(red);
		out.write(green);
		out.write(blue);
	}
	
	/**
	* Snag the pixels from an image.
	*
	* Copied verbatim from com.gurge.amd.TestQuantize by  <a href="http://www.gurge.com/amd/">Adam Doppelt</a>
	*/
	public static int[][] getPixels(Image image) throws IOException {
		int w = image.getWidth(null);
		int h = image.getHeight(null);        
		int pix[] = new int[w * h];
		PixelGrabber grabber = new PixelGrabber(image, 0, 0, w, h, pix, 0, w);
		
		try {
			if (grabber.grabPixels() != true) {
				throw new IOException("Grabber returned false: " +
				grabber.status());
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		int pixels[][] = new int[w][h];
		for (int x = w; x-- > 0; ) {
			for (int y = h; y-- > 0; ) {
				pixels[x][y] = pix[y * w + x];
			}
		}
		
		return pixels;
	}
}
