//------------------------------------------------------------------------------
// 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
 * 線形縮小フィルタ実装
 * @author Junpee
 */

#include "LampBasic.h"
#include "Core/Codec/LinearMinificationFilter/LinearMinificationFilter.h"

namespace Lamp{

//------------------------------------------------------------------------------
// フィルタ
void LinearMinificationFilter::filter(
	const Color3c* source, const DimensionI& sourceSize,
	Color3c* destination, const DimensionI destinationSize){
	// 引数チェック
	Assert(source != NULL);
	Assert(sourceSize.width != 0);
	Assert(sourceSize.height != 0);
	Assert((sourceSize.width != 1) || (sourceSize.height != 1));
	Assert(destination != NULL);
	Assert(destinationSize.width != 0);
	Assert(destinationSize.height != 0);
	Assert(((sourceSize.width / 2) == destinationSize.width) ||
		(sourceSize.width == 1));
	Assert(((sourceSize.height / 2) == destinationSize.height) ||
		(sourceSize.height == 1));
	// フィルタ
	for(int i = 0; i < destinationSize.height; i++){
		int offset = i * destinationSize.width;
		int sourceOffset0 = i * 2 * sourceSize.width;
		int sourceOffset1 = sourceOffset0 + sourceSize.width;
		if(sourceSize.height == 1){ sourceOffset1 -= sourceSize.width; }
		for(int j = 0; j < destinationSize.width; j++){
			int widthOffset0 = j * 2;
			int widthOffset1 = widthOffset0 + 1;
			if(sourceSize.width == 1){ widthOffset1 -= 1; }
			int r = ((int)source[sourceOffset0 + widthOffset0].r + 
				(int)source[sourceOffset0 + widthOffset1].r + 
				(int)source[sourceOffset1 + widthOffset0].r + 
				(int)source[sourceOffset1 + widthOffset1].r) / 4;
			int g = ((int)source[sourceOffset0 + widthOffset0].g + 
				(int)source[sourceOffset0 + widthOffset1].g + 
				(int)source[sourceOffset1 + widthOffset0].g + 
				(int)source[sourceOffset1 + widthOffset1].g) / 4;
			int b = ((int)source[sourceOffset0 + widthOffset0].b + 
				(int)source[sourceOffset0 + widthOffset1].b + 
				(int)source[sourceOffset1 + widthOffset0].b + 
				(int)source[sourceOffset1 + widthOffset1].b) / 4;
			destination[offset + j].set(r, g, b);
		}
	}
}
//------------------------------------------------------------------------------
// フィルタ
void LinearMinificationFilter::filter(
	const Color4c* source, const DimensionI& sourceSize,
	Color4c* destination, const DimensionI destinationSize){
	// 引数チェック
	Assert(source != NULL);
	Assert(sourceSize.width != 0);
	Assert(sourceSize.height != 0);
	Assert((sourceSize.width != 1) || (sourceSize.height != 1));
	Assert(destination != NULL);
	Assert(destinationSize.width != 0);
	Assert(destinationSize.height != 0);
	Assert(((sourceSize.width / 2) == destinationSize.width) ||
		(sourceSize.width == 1));
	Assert(((sourceSize.height / 2) == destinationSize.height) ||
		(sourceSize.height == 1));
	// フィルタ
	for(int i = 0; i < destinationSize.height; i++){
		int offset = i * destinationSize.width;
		int sourceOffset0 = i * 2 * sourceSize.width;
		int sourceOffset1 = sourceOffset0 + sourceSize.width;
		if(sourceSize.height == 1){ sourceOffset1 -= sourceSize.width; }
		for(int j = 0; j < destinationSize.width; j++){
			int widthOffset0 = j * 2;
			int widthOffset1 = widthOffset0 + 1;
			if(sourceSize.width == 1){ widthOffset1 -= 1; }
			int r = ((int)source[sourceOffset0 + widthOffset0].r + 
				(int)source[sourceOffset0 + widthOffset1].r + 
				(int)source[sourceOffset1 + widthOffset0].r + 
				(int)source[sourceOffset1 + widthOffset1].r) / 4;
			int g = ((int)source[sourceOffset0 + widthOffset0].g + 
				(int)source[sourceOffset0 + widthOffset1].g + 
				(int)source[sourceOffset1 + widthOffset0].g + 
				(int)source[sourceOffset1 + widthOffset1].g) / 4;
			int b = ((int)source[sourceOffset0 + widthOffset0].b + 
				(int)source[sourceOffset0 + widthOffset1].b + 
				(int)source[sourceOffset1 + widthOffset0].b + 
				(int)source[sourceOffset1 + widthOffset1].b) / 4;
			int a = ((int)source[sourceOffset0 + widthOffset0].a + 
				(int)source[sourceOffset0 + widthOffset1].a + 
				(int)source[sourceOffset1 + widthOffset0].a + 
				(int)source[sourceOffset1 + widthOffset1].a) / 4;
			destination[offset + j].set(r, g, b, a);
		}
	}
}
//------------------------------------------------------------------------------
} // End of namespace Lamp
//------------------------------------------------------------------------------
