// Coring 0.1
// Copyright 2004 Carl Ritson <critson@perlfu.co.uk>

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
// http://www.gnu.org/copyleft/gpl.html .

#include "windows.h"
#include "avisynth.h"

#include <stdio.h>

class Coring : public GenericVideoFilter {
	public: 
		Coring(PClip _child, int _threshold, bool _clipped, bool _debug, IScriptEnvironment* env);
		Coring::~Coring();
		PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env); 
//		bool __stdcall GetParity(int n);
	private:
		unsigned char	threshold;
		unsigned char	core_to;
		bool		clipped;
		bool		debug;

};

Coring::Coring(PClip _child, int _threshold, bool _clipped, bool _debug, IScriptEnvironment* env) 
	: GenericVideoFilter(_child), threshold(_threshold), clipped(_clipped), debug(_debug) {
	if (!vi.IsYV12())
		env->ThrowError("Coring: requires YV12 source");
	clipped = _clipped;
	if(clipped) {
		if(_threshold > 16 && _threshold < 235)
			threshold = 16 + _threshold;
		else if(_threshold >= 235)
			threshold = 235;
		else
			threshold = 16;
		core_to	= _debug ? 235 : 16;
	} else {
		if(_threshold > 0 && _threshold < 255)
			threshold = _threshold;
		else if(_threshold >= 255)
			threshold = 255;
		else
			threshold = 0;
		core_to	= _debug ? 255 : 16;
	}
}

Coring::~Coring() {
}

PVideoFrame __stdcall Coring::GetFrame(int n, IScriptEnvironment* env) {
	PVideoFrame frame = child->GetFrame(n, env);
	env->MakeWritable(&frame);
		
	unsigned char *ptrY = (unsigned char *) frame->GetWritePtr(PLANAR_Y);
	int row_sizeY = frame->GetRowSize(PLANAR_Y);
	int heightY = frame->GetHeight(PLANAR_Y);
	int h,w;
	
	for(h = 0; h < heightY; ++h) {
		unsigned char *p = ptrY + (h * row_sizeY);
		unsigned char *pEnd = p + row_sizeY;
		while(p < pEnd) {
			if(*p < threshold)
				*p = core_to;
			p++;
		}
	}

	return frame;
}

#if 0
bool __stdcall Coring::GetParity(int n) {
	return child->GetParity(n);
}
#endif

AVSValue __cdecl Create_Coring(AVSValue args, void*, IScriptEnvironment* env) {
	return new Coring(
			args[0].AsClip(),
			args[1].AsInt(0),
			args[2].AsBool(false),
			args[3].AsBool(false), 
			env);
}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
	env->AddFunction("Coring", "c[threshold]i[clipped]b[debug]b", 
			Create_Coring, 0);
	return "Coring filter";
}
