//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library 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.1 of the License, or (at your option) any later version.
//
// This library 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 this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library 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.1 of the License, or (at your option) any later version.
//
// This library 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 this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------
/** @file
 * Targaローダ実装
 * @author Junpee
 */

#include "LampBasic.h"
#include "Core/Codec/Tga/TargaLoader.h"
#include "Core/InputOutput/BinaryFileReader.h"

namespace Lamp{

//------------------------------------------------------------------------------
// コンストラクタ
TargaLoader::TargaLoader(BinaryReader* reader) : reader_(reader),
	size_(0, 0), hasAlpha_(false), allocateReader_(false){
}
//------------------------------------------------------------------------------
// コンストラクタ
TargaLoader::TargaLoader(const String& fileName) : reader_(NULL),
	size_(0, 0), hasAlpha_(false), allocateReader_(true){
	reader_ = new BinaryFileReader(fileName);
}
//------------------------------------------------------------------------------
// デストラクタ
TargaLoader::~TargaLoader(){
	if(allocateReader_){ delete reader_; }
}
//------------------------------------------------------------------------------
// ヘッダのロード
bool TargaLoader::loadHeader(){
	// イメージID
	u_char imageID = reader_->readUChar();
	Assert(imageID == 0);
	// カラーマップ非対応
	u_char colorMapFlag = reader_->readUChar();
	if(colorMapFlag == 1){
		ErrorOut("TargaLoader::loadHeader() Unsupported colorMap");
		return false;
	}
	// イメージタイプ
	u_char imageType = reader_->readUChar();
	if((imageType != 2) && (imageType != 10)){
		ErrorOut("TargaLoader::loadHeader() Unknown imageType %d", imageType);
		return false;
	}
	// 圧縮は非対応
	if(imageType == 10){
		ErrorOut("TargaLoader::loadHeader() Unsupported compress image");
		return false;
	}
	// カラーマップ詳細情報読み飛ばし
	reader_->readShort();
	reader_->readShort();
	reader_->readUChar();
	// X開始点
	int xOrigin = reader_->readShort();
	if(xOrigin != 0){
		ErrorOut("TargaLoader::loadHeader() Unsupported xOrigin %d", xOrigin);
		return false;
	}
	// Y開始点
	int yOrigin = reader_->readShort();
	if(yOrigin != 0){
		ErrorOut("TargaLoader::loadHeader() Unsupported yOrigin %d", yOrigin);
		return false;
	}
	// 幅
	size_.width = reader_->readShort();
	if(size_.width < 1){
		ErrorOut("TargaLoader::loadHeader() Invalid width %d", size_.width);
		return false;
	}
	// 高さ
	size_.height = reader_->readShort();
	if(size_.height < 1){
		ErrorOut("TargaLoader::loadHeader() Invalid height %d", size_.height);
		return false;
	}
	// ピクセルサイズ
	u_char pixelSize = reader_->readUChar();
	if((pixelSize != 24) && (pixelSize != 32)){
		ErrorOut("TargaLoader::loadHeader() Unsupported pixelSize %d",
			pixelSize);
		return false;
	}
	hasAlpha_ = (pixelSize == 32);
	// イメージ記述
	u_char imageDescriptor = reader_->readUChar();
	int alphaDepth = (imageDescriptor & 0xf);
	// アルファ深度チェック
	if(hasAlpha_){
		if(alphaDepth != 8){
			ErrorOut("TargaLoader::loadHeader() Invalid alphaDepth %d",
				alphaDepth);
			return false;
		}
	}else{
		if(alphaDepth != 0){
			ErrorOut("TargaLoader::loadHeader() Invalid alphaDepth %d",
				alphaDepth);
			return false;
		}
	}
	if((imageDescriptor & 0xf0) != 0){
		ErrorOut("TargaLoader::loadHeader() Invalid imageDescriptor %d",
			imageDescriptor);
		return false;
	}
	return true;
}
//------------------------------------------------------------------------------
// アルファ無しイメージのロード
void TargaLoader::loadImage(Color3c* output){
	// バッファにロード
	int bufferSize;
	if(hasAlpha_){ bufferSize = size_.width * size_.height * sizeof(Color4c); }
	else{ bufferSize = size_.width * size_.height * sizeof(Color3c); }
	u_char* buffer = new u_char[bufferSize];
	u_char* readAddress = buffer;
	reader_->readBytes(buffer, bufferSize);
	if(hasAlpha_){
		for(int i = size_.height - 1; i >= 0; i--){
			int offset = i * size_.width;
			for(int j = 0; j < size_.width; j++){
				u_char b = *readAddress;
				readAddress++;
				u_char g = *readAddress;
				readAddress++;
				u_char r = *readAddress;
				readAddress++;
				readAddress++;
				output[offset + j].set(r, g, b);
			}
		}
	}else{
		for(int i = size_.height - 1; i >= 0; i--){
			int offset = i * size_.width;
			for(int j = 0; j < size_.width; j++){
				u_char b = *readAddress;
				readAddress++;
				u_char g = *readAddress;
				readAddress++;
				u_char r = *readAddress;
				readAddress++;
				output[offset + j].set(r, g, b);
			}
		}
	}
	delete[] buffer;
}
//------------------------------------------------------------------------------
// アルファ有りイメージのロード
void TargaLoader::loadImage(Color4c* output){
	// バッファにロード
	int bufferSize;
	if(hasAlpha_){ bufferSize = size_.width * size_.height * sizeof(Color4c); }
	else{ bufferSize = size_.width * size_.height * sizeof(Color3c); }
	u_char* buffer = new u_char[bufferSize];
	u_char* readAddress = buffer;
	reader_->readBytes(buffer, bufferSize);
	if(hasAlpha_){
		for(int i = size_.height - 1; i >= 0; i--){
			int offset = i * size_.width;
			for(int j = 0; j < size_.width; j++){
				u_char b = *readAddress;
				readAddress++;
				u_char g = *readAddress;
				readAddress++;
				u_char r = *readAddress;
				readAddress++;
				u_char a = *readAddress;
				readAddress++;
				output[offset + j].set(r, g, b, a);
			}
		}
	}else{
		for(int i = size_.height - 1; i >= 0; i--){
			int offset = i * size_.width;
			for(int j = 0; j < size_.width; j++){
				u_char b = *readAddress;
				readAddress++;
				u_char g = *readAddress;
				readAddress++;
				u_char r = *readAddress;
				readAddress++;
				output[offset + j].set(r, g, b, 255);
			}
		}
	}
	delete[] buffer;
}
//------------------------------------------------------------------------------
} // End of namespace Lamp
//------------------------------------------------------------------------------
