#import  "MonoCtr.h"
#import  <appkit/Control.h>
#import  <stdio.h>
#import  <math.h>
#import  "../common.h"
#import  "MonotoneView.h"
#import  "imageOperation.h"
#import  "../ImageOpCtr.h"
#import  "../ImageOpr.h"

static void monoScale(unsigned char *buf, float contr, float bright, float *gscale)
{
	float	a, b, cn2;
	int	i, v;

	if (contr == 0.0) a = 1.0;
	else {
		cn2 = contr * contr;
		if (contr > 0.0)
			a = (contr < 1.0) ? (1.0 / (1.0 - cn2)) : 512.0;
		else
			a = 1.0 - cn2;
	}
#ifdef	BRIGHT_SQUARE
	b = bright * bright;
	if (bright < 0.0) b *= -1.0;
#else
	b = bright * bright * bright;
#endif
	b = (-1.0 - a) * 128.0 * (1.0 - b) + 256.0;

	for (i = 0; i < 256; i++) {
		v = (int)(a * gscale[i] + b + 0.5);
		buf[i] = (v > 255) ? 255 : ((v < 0) ? 0 : v);
	}
}


@implementation MonoCtr

- init
{
	int i;

	for (i = 0; i < 256; i++)
		tone[i] = i;
	gammaValue = 0.0;
	[self setGamma: 1.0];
	return self;
}

- setGamma:(float)gamma
{
	int	i;
	char	buf[8];

	if (gamma == gammaValue)
		return self;
	sprintf(buf, "%5.2f", gamma);
	[gammaText setStringValue: buf];
	if (gamma == 1.0) {
		for (i = 0; i < 256; i++)
			gammaScale[i] = i;
	}else {
		for (i = 0; i < 256; i++)
			gammaScale[i] = pow(i / 255.0, gamma) * 255.0;
	}
	gammaValue = gamma;
	return self;
}

- changeValue: sender
{
	[self setGamma: [gammaSlider floatValue]];
	monoScale(tone, [contrSlider floatValue],
			[brightSlider floatValue], gammaScale);
	[monoView setTone: tone];
	[monoView display];
	return self;
}

- reset: sender
{
	int i;

	[contrSlider setFloatValue: 0.0];
	[brightSlider setFloatValue: 0.0];
	[gammaSlider setFloatValue: 1.0];
	for (i = 0; i < 256; i++)
		tone[i] = i;
	[self setGamma: 1.0];
	[monoView setTone: tone];
	[monoView display];
	return self;
}

- monochrome: sender
{
	static int monokind[] = { Monochrome, Gray2Bits, BiLevel };

	[imageOpCtr monochrome: monokind[[sender selectedTag]]
		tone: tone method:[ditherSW selectedTag]];
	/* This message will be delegated to ImageOpr */
	return self;
}

- changeBrightness: sender
{
	[imageOpCtr brightness: tone];
	/* This message will be delegated to ImageOpr */
	return self;
}

@end
