#include <qapp.h>
#include <qslider.h>
#include <qdialog.h>
#include <qhbox.h>
#include <qmessagebox.h>
#include <qpushbutton.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qgroupbox.h>
#include <qlineedit.h>
#include <qvalidator.h>
#include <qcheckbox.h>

#include "recompressor.h"
#include "filters.h"

#include <strstream>
#include <cstdio>
#include <iostream>

using namespace std;

// base resizable dialog with Ok Cancel buttons
class OkCancelDialog : public QDialog
{
public:
    QGridLayout* m_pGl;
    OkCancelDialog(const char* title);
    int exec();
};

OkCancelDialog::OkCancelDialog(const char* title)
    :QDialog(0, title, true)
{
    setCaption(title);
    m_pGl = new QGridLayout(this);
    m_pGl->setMargin(5);
    m_pGl->setSpacing(5);
}

int OkCancelDialog::exec()
{
    QHBox* hb = new QHBox( this, "ok_cancel_hbox" );
    QWidget* w = new QWidget( hb, "ok_cancel_widget" );
    hb->setStretchFactor( w, 1 );
    QPushButton* ok = new QPushButton(tr("Ok"), hb);
    QPushButton* cancel = new QPushButton(tr("Cancel"), hb);
    m_pGl->addMultiCellWidget(hb, m_pGl->numRows(), m_pGl->numRows(),
			      0, m_pGl->numCols() - 1);

    connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
    connect(cancel, SIGNAL(clicked()), this, SLOT(reject()));

    return QDialog::exec();
}

// simple fullresizable dialog which handles sliders
class MySliderDialog : public OkCancelDialog
{
protected:
    int m_iRow;
public:
    MySliderDialog(const char* title) :OkCancelDialog(title), m_iRow(0) {}
    QSlider* addSlider(const char* param, const char* left = 0, const char* right = 0);
};

QSlider* MySliderDialog::addSlider(const char* param, const char* left, const char* right)
{
    QGroupBox* gb = new QGroupBox(this);
    gb->setTitle(param);
    gb->setColumnLayout(0, Qt::Vertical);
    QGridLayout* qvl = new QGridLayout(gb->layout());

    QSlider* s = new QSlider(gb, "");
    qvl->addMultiCellWidget(s, 0, 0, 0, 4);
    s->setTracking(false);
    s->setOrientation(QSlider::Horizontal);
    s->setTickmarks(QSlider::Below);

    if (left)
    {
	QLabel *l1 = new QLabel(gb, "");
	l1->setText(left);
	qvl->addWidget(l1, 1, 1);
    }

    if (right)
    {
	QLabel *l2 = new QLabel(gb, "");
	l2->setText(right);
	qvl->addWidget(l2, 1, 3);
    }

    qvl->setColStretch(0, 1);
    qvl->setColStretch(2, 10);
    qvl->setColStretch(4, 1);

    m_pGl->addMultiCellWidget(gb, m_iRow, m_iRow, 0, 2);
    m_iRow++;

    return s;
}



////////////
//  GAMMA
////////////

string GammaFilter::name()
{
    return string(tr("Gamma adjustment"));
}

string GammaFilter::fullname()
{
    char s[128];
    sprintf(s, tr("Adjust gamma by: %.2f"), _gamma);
    return s;
}

CImage* GammaFilter::process(CImage* im, int pos)
{
    im->AddRef();
    if(im->Depth()!=24)return im;
    if(!im->GetFmt()->IsRGB())im->ToRGB();
    for(int i=0; i<im->Height(); i++)
	for(int j=0; j<im->Width(); j++)
	{
	    unsigned char* c=im->At(j,i);
	    int z=c[0];
	    z=int(z*_gamma);
	    if(z>255)z=255;
	    c[0]=z;
	    z=c[1];
	    z=int(z*_gamma);
	    if(z>255)z=255;
	    c[1]=z;
	    z=c[2];
	    z=int(z*_gamma);
	    if(z>255)z=255;
	    c[2]=z;
	}
    return im;
}

void GammaFilter::about()
{
    QMessageBox::about(0, tr("About Gamma adjustment Filter"),
		       tr("This is a sample filter"));
}

void GammaFilter::config()
{
    MySliderDialog d(tr("Gamma adjustment"));
    QSlider* s = d.addSlider(tr("Gamma:"), "0", "5");

    double old_gamma=_gamma;
    s->setRange(0, 50);
    s->setValue(int(_gamma * 10));
    connect(s, SIGNAL(valueChanged(int)), this, SLOT(valueChanged(int)));

    if (d.exec() == QDialog::Rejected)
	_gamma=old_gamma;
    kernel->redraw();
}
void GammaFilter::valueChanged(int new_val)
{
    _gamma = new_val / 10.0;
    kernel->redraw();
}
string GammaFilter::save()
{
    ostrstream s;
    s<<_gamma;
    s.flush();
    return string(s.str(), s.tellp());
}

void GammaFilter::load(string str)
{
    istrstream s(str.c_str());
    s>>_gamma;
}

///////////
//  BLUR
///////////

string BlurFilter::name()
{
    return string(tr("Blur filter"));
}

string BlurFilter::fullname()
{
    char s[128];
    sprintf(s, tr("Blur - radius: %d"), _range);
    return s;
}

CImage* BlurFilter::process(CImage* im, int pos)
{
    im->AddRef();
    if(im->GetFmt()->IsRGB())
	im->ToYUV();

    im->Blur(_range);
    return im;
}

void BlurFilter::about()
{
    QMessageBox::about(0, tr("About Blur Filter"),
		       tr("This is a sample MMX filter"));
}

void BlurFilter::config()
{
    MySliderDialog d(tr("Blur adjustment"));
    QSlider* s = d.addSlider(tr("Radius:"), "1", "8");
    int old_range=_range;
    s->setRange(1, 8);
    s->setValue(_range);
    //s->setLineStep(1);
    s->setPageStep(1);
    connect(s, SIGNAL(valueChanged(int)), this, SLOT(valueChanged(int)));

    if(d.exec()==QDialog::Rejected)
	_range=old_range;
    kernel->redraw();
}
void BlurFilter::valueChanged(int new_val)
{
    _range=new_val;
    kernel->redraw();
}
string BlurFilter::save()
{
    ostrstream s;
    s<<_range;
    s.flush();
    return string(s.str(), s.tellp());
}

void BlurFilter::load(string str)
{
    istrstream s(str.c_str());
    s>>_range;
}


/////////////
//  REFRACT
/////////////

string RefractFilter::name()
{
    return string(tr("Refraction compensation"));
}

string RefractFilter::fullname()
{
    char s[128];
    sprintf(s, tr("Compensate refraction - distance: %d, power: %.3f"),
	    _dist, _power);
    return s;
}

void RefractFilter::about()
{
    QMessageBox::about(0, tr("About Refraction Filter"),
		       tr("This is a sample filter"));
}

void RefractFilter::config()
{
    MySliderDialog d(tr("Refraction compensation"));
    QSlider* s = d.addSlider(tr("Distance:"));
    int old_dist = _dist;
    double old_power = _power;

    s->setRange(1, 50);
    s->setValue(_dist);
    connect(s, SIGNAL(valueChanged(int)), this, SLOT(valueChanged1(int)));

    s = d.addSlider(tr("Power:"));
    s->setRange(1, 50);
    s->setValue(int(_power * 100));
    connect(s, SIGNAL(valueChanged(int)), this, SLOT(valueChanged2(int)));

    if (d.exec() == QDialog::Rejected)
    {
	_dist = old_dist;
	_power = old_power;
    }
    kernel->redraw();

}

void RefractFilter::valueChanged1(int new_val)
{
    _dist = new_val;
    kernel->redraw();
}
void RefractFilter::valueChanged2(int new_val)
{
    _power = new_val / 100.0;
    kernel->redraw();
}

CImage* RefractFilter::process(CImage* im, int pos)
{
    im->AddRef();
    if (im->Depth() != 24)
	return im;

    if (im->GetFmt()->IsRGB())
	im->ToYUV();

    CImage* refractor=new CImage(im);

    //refractor->Blur(2);
    int xd=im->Width();
    int yd=im->Height();

    uint8_t* data = im->Data();
    uint8_t* refdata = refractor->Data();
    for (unsigned int i=xd*yd*3-3; i>=3*_dist+9+9*xd; i-=3)
    {
	unsigned char* p = data+i;
	unsigned char* refp = refdata+i-3-3*xd;
	int brightness;
	if (((i-3*_dist)%(3*xd)<2.6*xd) || ((i%(3*xd)>xd)))
	    //brightness=(refp[-3*dist+0]+refp[-3*dist+1]+refp[-3*dist+2])/3;
	    //brightness=(.114*refp[-3*dist+0]+.586*refp[-3*dist+1]+.300*refp[-3*dist+2]);
	    //brightness=((col*)(refp-3*dist))->Y();
	    brightness=refp[-3*_dist];
	else
	    brightness=0;
	brightness=int(brightness*_power);
	//int y=(*p+power*p[-3*dist])/(1+power);
	/*if(y<0x10)y=0x10;
	 if(y>0xef)y=0xef;*/
	/*p[0]=max(0, unsigned char((p[0]+brightness)/(1+power)));
	 p[1]=max(0, unsigned char((p[1]+brightness)/(1+power)));
	 p[2]=max(0, unsigned char((p[2]+brightness)/(1+power)));*/
	p[0]=(unsigned char)((p[0]+brightness)/(1+_power));
	//p[1]=unsigned char((p[1]+brightness)/(1+power));
	//p[2]=unsigned char((p[2]+brightness)/(1+power));
	//*p=y;
    }
    refractor->Release();

    return im;
}
string RefractFilter::save()
{
    ostrstream s;
    s<<_dist<<" "<<_power;
    s.flush();
    return string(s.str(), s.tellp());
}

void RefractFilter::load(string str)
{
    istrstream s(str.c_str());
    s>>_dist>>_power;
    //    char z;
    //    s>>z;
    //    s>>_power;
}

////////////
//  NOISE
////////////

string NoiseFilter::name()
{
    return string(tr("Noise reduction"));
}
string NoiseFilter::fullname()
{
    char s[128];
    sprintf(s, tr("Reduce noise - quality: %d, edge radius: %d"),
	    _qual, _edge);
    return s;
}

void NoiseFilter::about()
{
    QMessageBox::about(0, tr("About Noise reduction Filter"),
		       tr("This is a sample filter"));
}

void NoiseFilter::config()
{
    MySliderDialog d(tr("Noise reduction"));
    QSlider* s = d.addSlider(tr("Quality:"), "850", "1000");
    int old_qual=_qual;
    s->setRange(850,1000);
    s->setValue(_qual);
    connect(s, SIGNAL(valueChanged(int)), this, SLOT(valueChanged1(int)));

    s = d.addSlider(tr("Radius:"), "1", "6");
    int old_edge=_edge;
    s->setRange(1,6);
    s->setValue(_edge);
    s->setPageStep(1);
    connect(s, SIGNAL(valueChanged(int)), this, SLOT(valueChanged2(int)));

    s = d.addSlider(tr(""), "1", "6"); // FIXME:  name of this parameter ????
    int old_zz=_zz;
    s->setRange(1,6);
    s->setValue(_zz);
    s->setPageStep(1);
    connect(s, SIGNAL(valueChanged(int)), this, SLOT(valueChanged3(int)));

    if (d.exec() == QDialog::Rejected)
    {
	_qual = old_qual;
	_edge = old_edge;
	_zz = old_zz;
    }
    kernel->redraw();
}


void NoiseFilter::valueChanged1(int new_val)
{
    _qual=new_val;
    kernel->redraw();
}

void NoiseFilter::valueChanged2(int new_val)
{
    _edge=new_val;
    kernel->redraw();
}

void NoiseFilter::valueChanged3(int new_val)
{
    _zz=new_val;
    kernel->redraw();
}

CImage* NoiseFilter::process(CImage* im, int pos)
{
    if (im->Depth()!=24)
    {
	cerr<<"ERROR: not 24bpp image"<<endl;
	im->AddRef(); // otherwice we return new CImage
	return im;
    }

    if (im->GetFmt()->IsRGB())
	im->ToYUV();

    //	Move(move);
    double m_dQual=_qual/1000.;

    CImage* result=new CImage(im);
    //	result->Enhance(256/m_dEnhQual);//128 ms
    //	result->Move(move);

    CEdgeRgn* edges=new CEdgeRgn(im, int(256/m_dQual), _edge, false, _zz);

    CImage* blurred=new CImage(result);
    blurred->Blur(1);//53 ms

    CImage* blurred3=new CImage(blurred);

    blurred3->Blur(2,1);

    CEdgeRgn* v2=new CEdgeRgn(edges);

    v2->Normalize();//17 ms

    v2->Blur(1);
    CEdgeRgn* v3=new CEdgeRgn(v2);
    v3->Blur(2,1);

    /*
     struct yuv* yptr=(struct yuv*)result->Data();
     for(int i=0; i<im->Width(); i++)
     for(int j=0; j<im->Height(); j++)
     {
     yptr[i+j*im->Width()].Cb=yptr[i+j*im->Width()].Cr=128;
     //	    if((*v2.at(i,j))<0)
     //		yptr[i+j*im->Width()].Y=128;
     //	    else
     yptr[i+j*im->Width()].Y=*(v2.at(i,j));
     }
     */
    const int _xd=im->Width();
    const int _yd=im->Height();
    //const int OFF1=-1-1*_xd;
    const int OFF2=-2-2*_xd;
    const int OFF4=-4-4*_xd;

    for(int i=4; i<_xd-4; i++)
    {
	for(int j=i+_xd*4; j<i+_xd*(_yd-4); j+=_xd)
	{
	    yuv* src=(yuv*)result->Data()+j;
	    yuv* v;
	    if((*v3->Offset(j+OFF4))==0)
	    {
	        v=(yuv*)blurred3->Data()+j+OFF4;
	        src->Y=v->Y;
	    }
	    else
	    if((*v2->Offset(j+OFF2))==0)
	    {
		v=(yuv*)blurred3->Data()+j+OFF4;
		src->Y=v->Y;
	    }
//	    else
//	    if((*edges->Offset(j))>128)
//	    {
//	        v=(yuv*)result->Data()+j;
//		src->Y=128;
//		src->Cr=64;
//		src->Cb=96;
//		continue;
//	    }
//    	    else
//	    {
//		src->Y=128;
//		src->Cr=96;
//		src->Cb=64;
//		continue;
//	    }
//	    src->Cr=v->Cr;
//    	    src->Cb=v->Cb;
	    else
		if((*v2->Offset(j+OFF2))==0)
		{
		    v=(yuv*)blurred->Data()+j+OFF2;
		    src->Y=v->Y;
		}
	    //	    else
	    //	    if((*edges->Offset(j))>128)
	    //	    {
	    //	        v=(yuv*)result->Data()+j;
	    //		src->Y=128;
	    //		src->Cr=64;
	    //		src->Cb=96;
	    //		continue;
	    //	    }
	    //    	    else
	    //	    {
	    //		src->Y=128;
	    //		src->Cr=96;
	    //		src->Cb=64;
	    //		continue;
	    //	    }
	    //	    src->Cr=v->Cr;
	    //    	    src->Cb=v->Cb;
	}
    }
    delete edges;
    delete blurred;
    delete blurred3;
    delete v2;
    delete v3;

    return result;
}
string NoiseFilter::save()
{
    ostrstream s;
    s<<_qual<<" "<<_edge<<" "<<_zz;
    s.flush();
    return string(s.str(), s.tellp());
}

void NoiseFilter::load(string str)
{
    istrstream s(str.c_str());
    //char z;
    cerr<<str<<endl;
    //    s>>_qual>>z>>_edge>>z>>_zz;
    s>>_qual>>_edge>>_zz;
    cerr<<_qual<<" "<<_edge<<" "<<_zz<<endl;

    //    s>>_qual>>" ">>_edge>>" ">>_zz;
    //    s.skip(1);
    //    s>>_edge;
    //    s.skip(1);
    //    s>>_zz;
}


///////////
// MOVE
//////////

string MoveFilter::name()
{
    return string(tr("Color move"));
}

string MoveFilter::fullname()
{
    char s[128];
    sprintf(s, tr("Move colors by %d"), _delta);
    return string(s);
}

CImage* MoveFilter::process(CImage* im, int pos)
{
    im->AddRef();
    if (im->Depth() != 24)
	return im;
    if(_delta==0)
	return im;
    if(!im->GetFmt()->IsRGB())im->ToYUV();
    yuv* ptr=(yuv*)im->Data();
    int csize=im->Width()*im->Height();
    if(_delta<0)
    {
	for(int i=0; i<csize+_delta; i++)
	{
	    ptr[i].Cb=ptr[i-_delta].Cb;
	    ptr[i].Cr=ptr[i-_delta].Cr;
	}
    }
    else
    {
	for(int i=csize-1; i>=_delta; i--)
	{
	    ptr[i].Cb=ptr[i-_delta].Cb;
	    ptr[i].Cr=ptr[i-_delta].Cr;
	}
    }
    return im;
}

void MoveFilter::about()
{
    QMessageBox::about(0, tr("About Color move Filter"),
		       tr("This is a sample filter"));
}

void MoveFilter::config()
{
    MySliderDialog d(tr("Color move adjustment"));
    QSlider* s = d.addSlider(tr("Color move:"), "-20", "20");
    int old_delta=_delta;
    s->setRange(-20, 20);
    s->setValue(_delta);
    connect(s, SIGNAL(valueChanged(int)), this, SLOT(valueChanged(int)));
    if (d.exec() == QDialog::Rejected)
	_delta = old_delta;
    kernel->redraw();
}

void MoveFilter::valueChanged(int new_val)
{
    _delta=new_val;
    kernel->redraw();
}

string MoveFilter::save()
{
    ostrstream s;
    s<<_delta;
    s.flush();
    return string(s.str(), s.tellp());
}

void MoveFilter::load(string str)
{
    istrstream s(str.c_str());
    s>>_delta;
}
/*
 CImage* SwapFilter::process(CImage* im, int pos)
 {
 //    if(im->yuv())im->ToRGB();
 if(!im->yuv())im->ToYUV();
 int csize=im->Width()*im->Height();
 yuv* ptr=(yuv*)im->Data();
 for(int i=0; i<csize; i++)
 {
 int t=ptr[i].r;
 ptr[i].r=ptr[i].g;
 ptr[i].g=t;
 //	col z=col(ptr[i]);
 //	*(col*)(ptr+i)=z;
 //	yuv z(0,0,0);
 //	z.Cr=_c1*ptr[i].Cr+_c2*ptr[i].Cb;
 //	z.Cb=_c3*ptr[i].Cr+_c4*ptr[i].Cb;
 int z=ptr[i].Y;
 z+=ptr[i].Cr;
 z+=ptr[i].Cb;
 z/=3;
 ptr[i].Y=z;
 ptr[i].Cr=ptr[i].Cb=128;
 //	ptr[i]=z;

 }
 im->addref();
 return im;
 }

 void SwapFilter::config()
 {
 QDialog d(0, "Noise reduction", true);
 d.setFixedSize(300,200);
 QSlider* slider1=new QSlider(&d, "");
 QSlider* slider2=new QSlider(&d, "");
 QSlider* slider3=new QSlider(&d, "");
 QSlider* slider4=new QSlider(&d, "");
 //    slider1->setTracking(false);
 //    slider2->setTracking(false);
 //    slider3->setTracking(false);
 //    slider4->setTracking(false);
 QLabel* label1=new QLabel(&d, "");
 label1->setText("Adjust qual:");
 label1->resize(70,15);
 label1->move(10,15);
 QLabel* label2=new QLabel(&d, "");
 label2->setText("Adjust radius:");
 label2->resize(70,15);
 label2->move(10,50);
 slider1->setOrientation(QSlider::Horizontal);
 slider1->setTickmarks(QSlider::Below);
 slider2->setOrientation(QSlider::Horizontal);
 slider2->setTickmarks(QSlider::Below);
 slider3->setOrientation(QSlider::Horizontal);
 slider3->setTickmarks(QSlider::Below);
 slider4->setOrientation(QSlider::Horizontal);
 slider4->setTickmarks(QSlider::Below);

 slider1->move(90,15);
 slider1->resize(200,25);
 slider1->setRange(-200,200);
 slider1->setValue(int(_c1*100));
 slider2->move(90,50);
 slider2->resize(200,25);
 slider2->setRange(-200,200);
 slider2->setValue(int(_c2*100));
 slider3->move(90,85);
 slider3->resize(200,25);
 slider3->setRange(-200,200);
 slider3->setValue(int(_c3*100));
 slider4->move(90,135);
 slider4->resize(200,25);
 slider4->setRange(-200,200);
 slider4->setValue(int(_c4*100));
 connect(slider1, SIGNAL(valueChanged(int)), this, SLOT(valueChanged1(int)));
 connect(slider2, SIGNAL(valueChanged(int)), this, SLOT(valueChanged2(int)));
 connect(slider3, SIGNAL(valueChanged(int)), this, SLOT(valueChanged3(int)));
 connect(slider4, SIGNAL(valueChanged(int)), this, SLOT(valueChanged4(int)));
 QPushButton* b_ok=new QPushButton("Ok", &d);
 b_ok->resize(40,20);
 b_ok->move(200,160);
 QPushButton* b_cancel=new QPushButton("Cancel", &d);
 b_cancel->resize(40,20);
 b_cancel->move(250,160);
 connect(b_ok, SIGNAL(clicked()), &d, SLOT(accept()));
 connect(b_cancel, SIGNAL(clicked()), &d, SLOT(reject()));
 d.exec();
 kernel->redraw();
 }
 void SwapFilter::valueChanged1(int new_val)
 {
 _c1=double(new_val)/100.;
 kernel->redraw();
 }
 void SwapFilter::valueChanged2(int new_val)
 {
 _c2=double(new_val)/100.;
 kernel->redraw();
 }
 void SwapFilter::valueChanged3(int new_val)
 {
 _c3=double(new_val)/100.;
 kernel->redraw();
 }
 void SwapFilter::valueChanged4(int new_val)
 {
 _c4=double(new_val)/100.;
 kernel->redraw();
 }
 */

void ScaleFilter::config()
{
    bool old_aspect = m_bAspect;
    bool old_percent = m_bPercent;
    double old_width = m_dWidth;
    double old_height = m_dHeight;

    OkCancelDialog d("Scale filter");

    QCheckBox* chb1 = new QCheckBox( &d, "scale_aspect" );
    chb1->setText( tr( "Preserve aspect ratio" ) );
    chb1->setChecked(m_bAspect);
    d.m_pGl->addWidget(chb1, 0, 0);

    connect(chb1, SIGNAL(clicked()), this, SLOT(onAspectToggle()));

    QCheckBox* chb2 = new QCheckBox( &d, "scale_percent" );
    chb2->setText( tr( "Use as percentage" ) );
    chb2->setChecked(m_bPercent);
    d.m_pGl->addWidget(chb2, 0, 1);

    connect(chb2, SIGNAL(clicked()), this, SLOT(onPercentToggle()));

    QDoubleValidator qv( 0.0, 1000.0, 3, &d );
    m_pLew = new QLineEdit( &d, "scale_width" );
    m_pLew->setValidator( &qv );
    d.m_pGl->addWidget( m_pLew, 1, 1 );

    connect(m_pLew, SIGNAL(returnPressed()), this, SLOT(valueChangedW()));

    m_pLeh = new QLineEdit( &d, "scale_height" );
    m_pLeh->setValidator( &qv );
    d.m_pGl->addWidget( m_pLeh, 2, 1 );

    connect(m_pLeh, SIGNAL(returnPressed()), this, SLOT(valueChangedH()));

    if (d.exec() == QDialog::Rejected)
    {
	m_bAspect = old_aspect;
	m_bPercent = old_percent;
	m_dWidth = old_width;
	m_dHeight = old_height;
    }
    kernel->redraw();
}

CImage* ScaleFilter::process(CImage* im, int pos)
{
    if (im->Depth()!=24)
    {
	im->AddRef();
	return im;
    }
    im->AddRef();
    return im;

    int w=im->Width()/2;
    int h=im->Height()/2;
    col* ptr=(col*)(im->Data());

    BitmapInfo info=*(im->GetFmt());
    adjust(info);
    CImage* result=new CImage(&info);
    col* dest=(col*)(result->Data());
    for(int i=0; i<h; i++)
    {
	for(int j=0; j<w; j++)
	{
	    *dest=*ptr;
	    dest++;
	    ptr+=2;
	}
	ptr+=2*w;
    }
    return result;
}

void ScaleFilter::adjust(BITMAPINFOHEADER& bh)
{
    double r = bh.biWidth / (double) bh.biHeight;
    if (m_bPercent)
    {
	bh.biWidth = int(bh.biWidth * (m_dWidth / 100.0));
	bh.biHeight = int(bh.biHeight * (m_dHeight / 100.0));
    }
    else
    {
	bh.biWidth = (int)m_dWidth;
	bh.biHeight = (int)m_dHeight;
    }

    if (m_bAspect)
        bh.biHeight = int(bh.biWidth / r);

    bh.biSizeImage = bh.biWidth * bh.biHeight * (bh.biBitCount / 8);
}

void ScaleFilter::onAspectToggle()
{
    m_bAspect = !m_bAspect;
    kernel->redraw();
}

void ScaleFilter::onPercentToggle()
{
    m_bPercent = !m_bPercent;
    kernel->redraw();
}

void ScaleFilter::valueChangedW()
{
    QString q = m_pLew->text();
    cout << "Width " << q << endl;
    kernel->redraw();
}

void ScaleFilter::valueChangedH()
{
    QString q = m_pLeh->text();
    cout << "Height " << q << endl;
    kernel->redraw();
}

#include "filters.moc"
