/*********************************************************************
 * This file is part of the PRAPI library.
 *
 * Copyright (C) 2001 Topi Mäenpää and Jaakko Viertola
 * All rights reserved.
 *
 * This program is free software. You can redistribute and/or modify
 * it under the terms of the free software licence found in the
 * accompanying file "COPYING". The licence terms must always be
 * redistributed with this source file. The above copyright notice
 * must be reproduced in all modified and unmodified copies of this
 * source file.
 *
 * $Revision: 1.10 $
 *********************************************************************/

#include "PnmCodec.h"

using namespace util;
using namespace std;
using namespace util::io;

namespace prapi
{
	template <> PnmCodec<RGBColor<> >::PnmCodec() : _bRaw(true), _bColor(true), _bAllowBinary(false) {}

	template <> PnmCodec<int>::PnmCodec() : _bRaw(true), _bColor(false), _bAllowBinary(false) {}

	template <>	void PnmCodec<RGBColor<> >::encodeMatrix(ostream& out, const Matrix<RGBColor<> >& mat) throw (MatrixException&, IOException&)
	{
		int width = mat.getColumns();
		int height = mat.getRows();
		int size = width*height*3;
		unsigned char* data = new unsigned char[size];
		int maxval = 255;
		int r,c,index=0;
		AllItems(r,c,mat)
			{
				RGBColor<> clr = mat(r,c);
				data[index++] = (unsigned char)clr.getRed();
				data[index++] = (unsigned char)clr.getGreen();
				data[index++] = (unsigned char)clr.getBlue();
			}
		PnmType type = _bRaw ? PNM_RAWBITS_PIXMAP : PNM_PLAIN_PIXMAP;
		writeMatrix(out,data,width,height,maxval,type);
		delete[] data;
	}

	template <>	void PnmCodec<int>::encodeMatrix(ostream& out, const Matrix<int>& mat) throw (MatrixException&, IOException&)
	{
		int width = mat.getColumns();
		int height = mat.getRows();
		int size = width*height;
		unsigned char* data = new unsigned char[size];
		int maxval = 0;
		int r,c,index=0;

		AllItems(r,c,mat)
			{
				data[index] = (unsigned char)mat(r,c);
				if (data[index] > maxval)
					maxval = data[index];
				index++;
			}

		PnmType type;
		if (_bAllowBinary && maxval <= 1)
			type = _bRaw ? PNM_RAWBITS_BITMAP : PNM_PLAIN_BITMAP;
		else
			type = _bRaw ? PNM_RAWBITS_GRAYMAP : PNM_PLAIN_GRAYMAP;
		writeMatrix(out,data,width,height,maxval,type);
		delete[] data;
	}



	template <>	void PnmCodec< RGBColor<> >::decodeMatrix(istream& in, Matrix<RGBColor<> >& mat) throw (MatrixException&, IOException&)
	{
		int width=0, height=0;
		unsigned char* data = readMatrix(in,width,height);
		if (!data) return;

		mat.setSize(height,width);

		RGBColor<>* matData = mat.getData();
		for (int dataIndex=0,index=0;dataIndex<width*height;dataIndex++)
			{
				RGBColor<> clr(data[index++],data[index++],data[index++]);
				matData[dataIndex] = clr;
			}
		delete[] data;
	}
	
	template <>	void PnmCodec<int>::decodeMatrix(istream& in, Matrix<int>& mat) throw (MatrixException&, IOException&)
	{
		int width=0, height=0;
		unsigned char* data = readMatrix(in,width,height);
		if (!data) return;

		mat.setSize(height,width);
		for (int i=0;i<width*height;i++)
			mat.getData()[i] = data[i];
		
		delete[] data;
	}
}
