#import "../ImageOpr.h"
#import <appkit/Application.h>
#import <appkit/publicWraps.h>
#import <appkit/NXBitmapImageRep.h>
#import <appkit/Control.h>
#import <appkit/Panel.h>
#import <appkit/TextField.h>
#import <stdio.h>
#import <stdlib.h>
#import <string.h>
#import <libc.h>
#import <streams/streams.h>
#import "../TVController.h"
#import "../ToyWin.h"
#import "../ToyWinEPS.h"
#import "../ToyView.h"
#import "../common.h"
#import "../getpixel.h"
#import "imageOperation.h"
#import "TonePanelCtrl.h"


@implementation ImageOpr (ColorToneCtrl)

static int color_tone(const commonInfo *cinf,
		const float *ratio, unsigned char **planes)
{
	int total, i, idx;
	int pnum, v;
	int elm[MAXPLANE];
	int alp, err;
	float	avr;

	pnum = cinf->numcolors;	/* must be 3 */
	if (cinf->alpha) alp = pnum++;
	else alp = 0;
	err = allocImage(planes, cinf->width, cinf->height, 8, pnum);
	if (err) return err;

	total = cinf->height * cinf->width;
	for (idx = 0; idx < total; idx++) {
		getPixel(&elm[0], &elm[1], &elm[2], &elm[3]);
		avr = (elm[0] + elm[1] + elm[2]) / 3.0;
		for (i = 0; i < 3; i++) {
			if ((v = elm[i] - avr) > 0.0)
				v = v * ratio[i] + avr;
			else if (v < 0.0)
				v = v * ratio[i+3] + avr;
			else
				v = avr;
			planes[i][idx] = (v >= 255) ? 255 : ((v <= 0) ? 0 : v);
		}
		if (alp) planes[alp][idx] = elm[3];
	}
	return 0;
}

/* Local Method */
- (int)doEnhance:(const char *)fn info:(const commonInfo *)cinf
	parent:(ToyWin *)parent with:(const float *)ratio
{
	ToyWin *tw;
	int	err;
	commonInfo *newinf = NULL;
	unsigned char *working[MAXPLANE];

	working[0] = NULL;
	tw = NULL;
	if ((newinf = (commonInfo *)malloc(sizeof(commonInfo))) == NULL)
		goto ErrEXIT;
	*newinf = *cinf;
	newinf->bits = 8;
	newinf->isplanar = YES;
	newinf->xbytes = newinf->width;
	newinf->palsteps = 0;
	newinf->palette = NULL;
	[theController messageDisplay: "Enhancing..."];
	tw = [[ToyWin alloc] init:parent by:ColorTone];
	[tw initLocateWindow:fn width:newinf->width height:newinf->height];

	err = color_tone(cinf, ratio, working);
	[theController messageDisplay:NULL];
	if (err) goto ErrEXIT;
	[tw makeComment: newinf from: cinf];
	if ([tw drawView:working info: newinf] == nil)
		goto ErrEXIT;
	[theController newWindow: tw];

	return 0;

ErrEXIT:
	if (working[0]) free((void *)working[0]);
	if (newinf) free((void *)newinf);
	if (tw) [tw free];
	return Err_MEMORY;
}


- colorToneEnhance:(const float *)ratio
{
	ToyWin	*tw;
	ToyView	*tv = NULL;
	NXImageRep	*rep;
	commonInfo	*cinf;
	unsigned char	*map[MAXPLANE];
	char	fn[MAXFILENAMELEN];
	const char *fnam;
	int	i, err;

	err = 1;
	for (i = 0; i < N_Colors; i++)
		if (ratio[i] != 1.0) {
			err = 0;
			break;
		}
	if (err || (tw = [self keyParentWindow:ColorTone]) == nil) {
		NXBeep();
		return self;
	}
	tv = [tw toyView];
	fnam = [tw filename];
	cinf = [tv commonInfo];
	if (cinf->numcolors == 1) {
		warnAlert(fnam, Err_OPR_IMPL);
		return self;
	}
	if (![self checkCommonInfo:cinf filename:fnam])
		return self;

	rep = [[tv image] bestRepresentation];
	[(NXBitmapImageRep *)rep getDataPlanes: map];
	if ((err = initGetPixel(cinf)) != 0) {
		errAlert(fnam, err);
		return self;
	}
	resetPixel(map, 0);
	sprintf(fn, "%s(ColorTone)", fnam);
	err = [self doEnhance:fn info:cinf parent:tw with:ratio];
	if (err != 0)
		errAlert(fnam, err);
	return self;
}

@end
