#pragma once

#include <iostream>
#include <fstream>

#include "../lm/vmatrix.h"
#include "color.h"


namespace lgr
{


//! ビットマップデータなどを管理するクラス
template<typename T>
class RawImage : public lm::matrix<T>
{
public:
	RawImage(void)                                               : lm::matrix<T>() {}
	RawImage(size_t num_x, size_t num_y)                         : lm::matrix<T>(num_x,num_y) {}
	RawImage(size_t num_x, size_t num_y, const T& initial_value) : lm::matrix<T>(num_x,num_y,initial_value) {}
	RawImage(const RawImage<T>& m)                               : lm::matrix<T>(m) {}

public:
	bool SaveRawImage( std::ostream& ost ) const;
	bool SaveRawImage( const std::string& filename ) const;
	bool LoadRawImage( std::istream& ist );
	bool LoadRawImage( const std::string& filename );
};

typedef RawImage<color3b> RawImage3b;
typedef RawImage<color3f> RawImage3f;
typedef RawImage<color3i> RawImage3i;
typedef RawImage<color3d> RawImage3d;
typedef RawImage<color4b> RawImage4b;
typedef RawImage<color4f> RawImage4f;
typedef RawImage<color4i> RawImage4i;
typedef RawImage<color4d> RawImage4d;



// -----------------------------------------------------------------------------------------------------------------------------------------
// implements

template<typename T> inline
bool RawImage<T>::SaveRawImage( std::ostream& ost ) const
{
	ost.write( reinterpret_cast<const char*>( &m_size_x ) , sizeof( m_size_x )   );
	ost.write( reinterpret_cast<const char*>( &m_size_y ) , sizeof( m_size_y )   );
	if( !empty() )
	{
		ost.write( reinterpret_cast<const char*>( v() ) , sizeof( T ) * size() );
	}

	return true;
}

template<typename T> inline
bool RawImage<T>::SaveRawImage( const std::string& filename ) const
{
	std::ofstream ofs( filename.c_str() , std::ios::binary );
	if( ofs.is_open() == false ) return false;

	return SaveRawImage( ofs );
}

template<typename T> inline
bool RawImage<T>::LoadRawImage( std::istream& ist )
{
	ist.read( reinterpret_cast<char*>( &m_size_x ) , sizeof( m_size_x )   );
	ist.read( reinterpret_cast<char*>( &m_size_y ) , sizeof( m_size_y )   );
	buf.clear();
	buf.resize( m_size_x * m_size_y );

	if( !empty() )
	{
		ist.read( reinterpret_cast<char*>( v() ) , sizeof( T ) * size() );
	}

	return true;
}

template<typename T> inline
bool RawImage<T>::LoadRawImage( const std::string& filename )
{
	std::ifstream ifs( filename.c_str() , std::ios::binary );
	if( ifs.is_open() == false ) return false;

	return LoadRawImage( ifs );
}


}
