// basisu_resampler_filters.cpp
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "basisu_resampler_filters.h"

#ifndef M_PI
	#define M_PI 3.14159265358979323846
#endif

namespace basisu
{
#define BOX_FILTER_SUPPORT (0.5f)
	static float box_filter(float t) /* pulse/Fourier window */
	{
		// make_clist() calls the filter function with t inverted (pos = left, neg = right)
		if ((t >= -0.5f) && (t < 0.5f))
			return 1.0f;
		else
			return 0.0f;
	}

#define TENT_FILTER_SUPPORT (1.0f)
	static float tent_filter(float t) /* box (*) box, bilinear/triangle */
	{
		if (t < 0.0f)
			t = -t;

		if (t < 1.0f)
			return 1.0f - t;
		else
			return 0.0f;
	}

#define BELL_SUPPORT (1.5f)
	static float bell_filter(float t) /* box (*) box (*) box */
	{
		if (t < 0.0f)
			t = -t;

		if (t < .5f)
			return (.75f - (t * t));

		if (t < 1.5f)
		{
			t = (t - 1.5f);
			return (.5f * (t * t));
		}

		return (0.0f);
	}

#define B_SPLINE_SUPPORT (2.0f)
	static float B_spline_filter(float t) /* box (*) box (*) box (*) box */
	{
		float tt;

		if (t < 0.0f)
			t = -t;

		if (t < 1.0f)
		{
			tt = t * t;
			return ((.5f * tt * t) - tt + (2.0f / 3.0f));
		}
		else if (t < 2.0f)
		{
			t = 2.0f - t;
			return ((1.0f / 6.0f) * (t * t * t));
		}

		return (0.0f);
	}

	// Dodgson, N., "Quadratic Interpolation for Image Resampling"
#define QUADRATIC_SUPPORT 1.5f
	static float quadratic(float t, const float R)
	{
		if (t < 0.0f)
			t = -t;
		if (t < QUADRATIC_SUPPORT)
		{
			float tt = t * t;
			if (t <= .5f)
				return (-2.0f * R) * tt + .5f * (R + 1.0f);
			else
				return (R * tt) + (-2.0f * R - .5f) * t + (3.0f / 4.0f) * (R + 1.0f);
		}
		else
			return 0.0f;
	}

	static float quadratic_interp_filter(float t)
	{
		return quadratic(t, 1.0f);
	}

	static float quadratic_approx_filter(float t)
	{
		return quadratic(t, .5f);
	}

	static float quadratic_mix_filter(float t)
	{
		return quadratic(t, .8f);
	}

	// Mitchell, D. and A. Netravali, "Reconstruction Filters in Computer Graphics."
	// Computer Graphics, Vol. 22, No. 4, pp. 221-228.
	// (B, C)
	// (1/3, 1/3)  - Defaults recommended by Mitchell and Netravali
	// (1, 0)	   - Equivalent to the Cubic B-Spline
	// (0, 0.5)		- Equivalent to the Catmull-Rom Spline
	// (0, C)		- The family of Cardinal Cubic Splines
	// (B, 0)		- Duff's tensioned B-Splines.
	static float mitchell(float t, const float B, const float C)
	{
		float tt;

		tt = t * t;

		if (t < 0.0f)
			t = -t;

		if (t < 1.0f)
		{
			t = (((12.0f - 9.0f * B - 6.0f * C) * (t * tt)) + ((-18.0f + 12.0f * B + 6.0f * C) * tt) + (6.0f - 2.0f * B));

			return (t / 6.0f);
		}
		else if (t < 2.0f)
		{
			t = (((-1.0f * B - 6.0f * C) * (t * tt)) + ((6.0f * B + 30.0f * C) * tt) + ((-12.0f * B - 48.0f * C) * t) + (8.0f * B + 24.0f * C));

			return (t / 6.0f);
		}

		return (0.0f);
	}

#define MITCHELL_SUPPORT (2.0f)
	static float mitchell_filter(float t)
	{
		return mitchell(t, 1.0f / 3.0f, 1.0f / 3.0f);
	}

#define CATMULL_ROM_SUPPORT (2.0f)
	static float catmull_rom_filter(float t)
	{
		return mitchell(t, 0.0f, .5f);
	}

	static double sinc(double x)
	{
		x = (x * M_PI);

		if ((x < 0.01f) && (x > -0.01f))
			return 1.0f + x * x * (-1.0f / 6.0f + x * x * 1.0f / 120.0f);

		return sin(x) / x;
	}

	static float clean(double t)
	{
		const float EPSILON = .0000125f;
		if (fabs(t) < EPSILON)
			return 0.0f;
		return (float)t;
	}

	//static double blackman_window(double x)
	//{
	//	return .42f + .50f * cos(M_PI*x) + .08f * cos(2.0f*M_PI*x);
	//}

	static double blackman_exact_window(double x)
	{
		return 0.42659071f + 0.49656062f * cos(M_PI * x) + 0.07684867f * cos(2.0f * M_PI * x);
	}

#define BLACKMAN_SUPPORT (3.0f)
	static float blackman_filter(float t)
	{
		if (t < 0.0f)
			t = -t;

		if (t < 3.0f)
			//return clean(sinc(t) * blackman_window(t / 3.0f));
			return clean(sinc(t) * blackman_exact_window(t / 3.0f));
		else
			return (0.0f);
	}

#define GAUSSIAN_SUPPORT (1.25f)
	static float gaussian_filter(float t) // with blackman window
	{
		if (t < 0)
			t = -t;
		if (t < GAUSSIAN_SUPPORT)
			return clean(exp(-2.0f * t * t) * sqrt(2.0f / M_PI) * blackman_exact_window(t / GAUSSIAN_SUPPORT));
		else
			return 0.0f;
	}

	// Windowed sinc -- see "Jimm Blinn's Corner: Dirty Pixels" pg. 26.
#define LANCZOS3_SUPPORT (3.0f)
	static float lanczos3_filter(float t)
	{
		if (t < 0.0f)
			t = -t;

		if (t < 3.0f)
			return clean(sinc(t) * sinc(t / 3.0f));
		else
			return (0.0f);
	}

#define LANCZOS4_SUPPORT (4.0f)
	static float lanczos4_filter(float t)
	{
		if (t < 0.0f)
			t = -t;

		if (t < 4.0f)
			return clean(sinc(t) * sinc(t / 4.0f));
		else
			return (0.0f);
	}

#define LANCZOS6_SUPPORT (6.0f)
	static float lanczos6_filter(float t)
	{
		if (t < 0.0f)
			t = -t;

		if (t < 6.0f)
			return clean(sinc(t) * sinc(t / 6.0f));
		else
			return (0.0f);
	}

#define LANCZOS12_SUPPORT (12.0f)
	static float lanczos12_filter(float t)
	{
		if (t < 0.0f)
			t = -t;

		if (t < 12.0f)
			return clean(sinc(t) * sinc(t / 12.0f));
		else
			return (0.0f);
	}

	static double bessel0(double x)
	{
		const double EPSILON_RATIO = 1E-16;
		double xh, sum, pow, ds;
		int k;

		xh = 0.5 * x;
		sum = 1.0;
		pow = 1.0;
		k = 0;
		ds = 1.0;
		while (ds > sum * EPSILON_RATIO) // FIXME: Shouldn't this stop after X iterations for max. safety?
		{
			++k;
			pow = pow * (xh / k);
			ds = pow * pow;
			sum = sum + ds;
		}

		return sum;
	}

	static const float KAISER_ALPHA = 4.0;
	static double kaiser(double alpha, double half_width, double x)
	{
		const double ratio = (x / half_width);
		return bessel0(alpha * sqrt(1 - ratio * ratio)) / bessel0(alpha);
	}

#define KAISER_SUPPORT 3
	static float kaiser_filter(float t)
	{
		if (t < 0.0f)
			t = -t;

		if (t < KAISER_SUPPORT)
		{
			// db atten
			const float att = 40.0f;
			const float alpha = (float)(exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886 * (att - 20.96));
			//const float alpha = KAISER_ALPHA;
			return (float)clean(sinc(t) * kaiser(alpha, KAISER_SUPPORT, t));
		}

		return 0.0f;
	}

	const resample_filter g_resample_filters[] =
	{
		 { "box", box_filter, BOX_FILTER_SUPPORT }, { "tent", tent_filter, TENT_FILTER_SUPPORT }, { "bell", bell_filter, BELL_SUPPORT }, { "b-spline", B_spline_filter, B_SPLINE_SUPPORT },
		 { "mitchell", mitchell_filter, MITCHELL_SUPPORT }, { "lanczos3", lanczos3_filter, LANCZOS3_SUPPORT }, { "blackman", blackman_filter, BLACKMAN_SUPPORT }, { "lanczos4", lanczos4_filter, LANCZOS4_SUPPORT },
		 { "lanczos6", lanczos6_filter, LANCZOS6_SUPPORT }, { "lanczos12", lanczos12_filter, LANCZOS12_SUPPORT }, { "kaiser", kaiser_filter, KAISER_SUPPORT }, { "gaussian", gaussian_filter, GAUSSIAN_SUPPORT },
		 { "catmullrom", catmull_rom_filter, CATMULL_ROM_SUPPORT }, { "quadratic_interp", quadratic_interp_filter, QUADRATIC_SUPPORT }, { "quadratic_approx", quadratic_approx_filter, QUADRATIC_SUPPORT }, { "quadratic_mix", quadratic_mix_filter, QUADRATIC_SUPPORT },
	};

	const int g_num_resample_filters = BASISU_ARRAY_SIZE(g_resample_filters);

	int find_resample_filter(const char *pName)
	{
		for (int i = 0; i < g_num_resample_filters; i++)
			if (strcmp(pName, g_resample_filters[i].name) == 0)
				return i;
		return -1;
	}
} // namespace basisu
