/* NAME: Kirill Vasil'evich Timofeev, 322
 * ASGN: N1
 */

#include <QtGui>

 #include "mainwindow.h"

 MainWindow::MainWindow()
 {
     isModified = false;
     isOpened = false;
     r = "You are so Inaccuratly...";
     window = new QWidget;
     tabWidget = new QTabWidget;
     labelIm = new QLabel;

     harshness = new QWidget;
     gaussfiltration = new QWidget;
     medianfiltration = new QWidget;
     zooming = new QWidget;
     rotation = new QWidget;
     wave = new QWidget;

     // medianfiltration

     lm = new QHBoxLayout;
     spinBoxM = new QSpinBox;
     butM = new QPushButton("&Apply");
     spinBoxM->setRange(3 , 9);
     spinBoxM->setSingleStep(2);
     spinBoxM->setValue(3);
     inputmed(3);
     QLabel *labelM = new QLabel("[3; 5; 7; 9]");
     lm->addWidget(spinBoxM);
     lm->addWidget(labelM);
     lm->addWidget(butM, 8);
     medianfiltration->setLayout(lm);

     // gaussfiltration

     lf1 = new QHBoxLayout;
     spinBoxF1 = new QDoubleSpinBox;
     butF1 = new QPushButton("&Apply");
     spinBoxF1->setRange(0.01 , 5.0);
     spinBoxF1->setSingleStep(0.01);
     spinBoxF1->setValue(1);
     inputgau(1);
     QLabel *labelF = new QLabel("[0.01,5.0]");
     lf1->addWidget(spinBoxF1);
     lf1->addWidget(labelF);
     lf1->addWidget(butF1, 8);
     gaussfiltration->setLayout(lf1);

     //rotation

     lg1 = new QHBoxLayout;
     spinBoxG1 = new QDoubleSpinBox;
     butG1 = new QPushButton("&Apply");
     spinBoxG1->setRange(-180,180);
     spinBoxG1->setSuffix("'");
     spinBoxG1->setValue(0);
     inputrot(0);
     QLabel *labelG12 = new QLabel("[-180',180']");
     lg1->addWidget(spinBoxG1);
     lg1->addWidget(labelG12);
     lg1->addWidget(butG1, 8);
     rotation->setLayout(lg1);

     //zoom
     lg0 = new QVBoxLayout;
     lg2 = new QHBoxLayout;
     spinBoxG2 = new QDoubleSpinBox;
     butG2 = new QPushButton("&Apply");
     spinBoxG2->setRange(1, 10000);
     spinBoxG2->setSingleStep(0.01);
     spinBoxG2->setSuffix("%");

     inputzoo(100);
     QLabel *labelG21 = new QLabel("Correct");
     QLabel *labelG22 = new QLabel("[1,10000]");
     lg2->addWidget(labelG21);
     lg2->addWidget(spinBoxG2);
     lg2->addWidget(labelG22);
     lg2->addWidget(butG2, 8);
     lg = new QHBoxLayout;
     spinBoxG = new QDoubleSpinBox;
     butG = new QPushButton("&Apply");
     spinBoxG->setRange(1, 10000);
     spinBoxG->setSingleStep(0.01);
     spinBoxG->setSuffix("%");
     QObject::connect(spinBoxG2, SIGNAL(valueChanged(double)),
     spinBoxG, SLOT(setValue(double)));
     QObject::connect(spinBoxG, SIGNAL(valueChanged(double)),
     spinBoxG2, SLOT(setValue(double)));
     spinBoxG2->setValue(100);
     QLabel *labelG31 = new QLabel("Another");
     QLabel *labelG32 = new QLabel("[1,10000]");
     lg->addWidget(labelG31);
     lg->addWidget(spinBoxG);
     lg->addWidget(labelG32);
     lg->addWidget(butG, 8);
     lg0->addLayout(lg);
     lg0->addLayout(lg2);
     zooming->setLayout(lg0);

     //Harshness

     lh = new QHBoxLayout;
     spinBoxH = new QDoubleSpinBox;
     butH = new QPushButton("&Apply");
     spinBoxH->setRange(0, 3);
     spinBoxH->setSingleStep(0.01);
     spinBoxH->setValue(0);
     inputsha(0);
     QLabel *labelH = new QLabel("[0,3]");
     lh->addWidget(spinBoxH);
     lh->addWidget(labelH);
     lh->addWidget(butH, 8);
     harshness->setLayout(lh);

     //Waves

     lw0 = new QVBoxLayout;
     lw1 = new QHBoxLayout;
     lw2 = new QHBoxLayout;
     spinBoxW1 = new QDoubleSpinBox;
     spinBoxW2 = new QDoubleSpinBox;
     butW = new QPushButton("&Apply");
     spinBoxW1->setRange(0, 100);
     spinBoxW1->setSingleStep(0.01);
     spinBoxW1->setValue(0);
     inputwadl(0);
     spinBoxW2->setRange(0, 100);
     spinBoxW2->setSingleStep(0.01);
     spinBoxW2->setValue(0);
     inputwaam(0);
     QLabel *labelW11 = new QLabel("Wawe length");
     QLabel *labelW12 = new QLabel("[0,10]");
     QLabel *labelW21 = new QLabel("Amplituda");
     QLabel *labelW22 = new QLabel("[0,10]");
     lw1->addWidget(labelW11);
     lw1->addWidget(spinBoxW1);
     lw1->addWidget(labelW12);
     lw2->addWidget(labelW21);
     lw2->addWidget(spinBoxW2);
     lw2->addWidget(labelW22);
     lw0->addLayout(lw1);
     lw0->addLayout(lw2);
     lw0->addWidget(butW, 8);
     wave->setLayout(lw0);

     //window

     tabWidget->addTab(harshness,"Harshness");
     tabWidget->addTab(medianfiltration,"Median Filtration");
     tabWidget->addTab(gaussfiltration,"Gauss Filtration");
     tabWidget->addTab(rotation,"Rotation");
     tabWidget->addTab(zooming,"Zooming");
     tabWidget->addTab(wave,"Transversal-longitudinal Waves");
     tabWidget->showMinimized();
     mainLayout = new QVBoxLayout;
     mainLayout->setSizeConstraint(QLayout::SetMinimumSize);
     mainLayout->addWidget(labelIm);
     mainLayout->addWidget(tabWidget);
     window->setLayout(mainLayout);
     setCentralWidget(window);

     createActions();
     createMenus();
     createStatusBar();

     setUnifiedTitleAndToolBarOnMac(true);
 }

 MainWindow::~MainWindow()
 {
     //Acts

     delete openImAct;
     delete saveImAct;
     delete saveImAsAct;
     delete exitAct;
     delete zoomAct;
     delete zoom2Act;
     delete rotationAct;
     delete gaussAct;
     delete linearAct;
     delete channelAct;
     delete harshnessAct;
     delete wavesAct;
     delete medianAct;
     delete grayworldAct;

     // medianfiltration

     delete spinBoxM;
     delete butM;
     delete lm;

     // gaussfiltration

     delete spinBoxF1;
     delete butF1;
     delete lf1;

     //rotation

     delete spinBoxG1;
     delete butG1;
     delete lg1;

     //zoom

     delete spinBoxG2;
     delete butG2;
     delete spinBoxG;
     delete butG;
     delete lg;
     delete lg2;
     delete lg0;

     //Harshness

     delete spinBoxH;
     delete butH;
     delete lh;

     //Waves

     delete spinBoxW1;
     delete spinBoxW2;
     delete butW;
     delete lw2;
     delete lw1;
     delete lw0;

     //window

     delete harshness;
     delete gaussfiltration;
     delete medianfiltration;
     delete zooming;
     delete rotation;
     delete wave;

     delete labelIm;
     delete tabWidget;
     delete window;


 }


void MainWindow::openIm()
 {
    bool t=true;
    if (isModified) t = maybeSave();
    if (t)
    {
        QString fileName = QFileDialog::getOpenFileName(this);
        if (!fileName.isEmpty())
        {
            if (isOpened)
            {
                delete image;
                delete curImage;
                labelIm->clear();
                isModified = false;
            }
            image = new QPixmap;
            while (t)
            {
                t = !(image->load(fileName));
                QMessageBox msgBox;
                if (t)
                {
                    msgBox.setText("Damn! File is incorrect!");
                    statusBar()->showMessage(tr("Image wasn't Opened!"), 2000);
                    msgBox.exec();
                    fileName = QFileDialog::getOpenFileName(this);
                }
            }
            isOpened = true;
            labelIm->setPixmap(*image);
            curFile = fileName;
            curImage=new QImage(image->toImage());
            labelIm->setMinimumSize(curImage->width(), curImage->height());
            if ((image->width()) > 768)
            {
                double p =  (float)76800 / (image->width());
                inputzoo(p);
                zoom2();
            }
            koefp = 100;
            koefg = 0;
            spinBoxG2->setValue(100);
            spinBoxG1->setValue(0);
            repaint();
            statusBar()->showMessage(tr("Image was Opened"), 2000);
        }
    }
    return;
}

bool MainWindow::saveIm()
{
    if (isOpened)
    {
        if (curFile.isEmpty())
        {
            return saveImAs();
        }
        else
        {
            QFile file(curFile);
            file.open(QFile::WriteOnly);
            (labelIm->pixmap())->save(curFile);
            statusBar()->showMessage(tr("Image was Saved"), 2000);
            isModified = false;
            return true;
        }
    }
    QMessageBox msgBox;
    msgBox.setText("Damn! You forgot to open Image!!!");
    msgBox.exec();
    statusBar()->showMessage(tr("Image wasn't Saved"), 2000);
    return false;
}

bool MainWindow::saveImAs()
{
    if (isOpened)
    {
        QString fileName = QFileDialog::getSaveFileName(this);
        if (fileName.isEmpty())
            return false;
        QFile file(fileName);
        file.open(QFile::WriteOnly);
        (labelIm->pixmap())->save(fileName);
        statusBar()->showMessage(tr("Image was Saved Ass"), 2000);
        isModified = false;
        return true;//
    }
    QMessageBox msgBox;
    msgBox.setText("Damn! You forgot to open Image!!!");
    msgBox.exec();
    statusBar()->showMessage(tr("Image wasn't Saved Ass"), 2000);
    return false;
}

void MainWindow::exit()
{
    if (isModified)
        if (!maybeSave()) return;
    QMessageBox msgBox;
    msgBox.setWindowTitle("Exit");
    msgBox.setText("Thank you for using my Program)) Goodbye!!");
    msgBox.exec();
    close();
}


void MainWindow::zoom()//увеличение; 100% - самое начальное положение
{
    if (isOpened)
    {
        double koef = zoo;
        double xtemp, ytemp;
        int xneed, yneed, xtempi, ytempi;
        int red,green,blue;
        QImage *Temp = new QImage(curImage->width(),curImage->height(),QImage::Format_RGB32);
        double hdr, wdr, k = (float)koef / koefp;
        int crotx = (curImage->width() - 1) / 2, croty = (curImage->height() - 1) / 2;
        for (int i = 0; i < (Temp->width()); i++)
        {
            for (int j = 0; j < (Temp->height()); j++)
            {
                if ( (i == crotx)&&(j == croty) )
                {
                    Temp->setPixel(i,j,curImage->pixel(i,j));
                    continue;
                }
                xtemp = ((i - crotx) / k) + crotx;
                ytemp = croty - ((croty - j) / k) ;
                xtempi = (int) trunc(xtemp);
                xneed = xtempi;
                if (xtemp != xtempi)
                    xneed++;
                ytempi = (int)trunc(ytemp);
                yneed = ytempi;
                if (ytemp != ytempi)
                    yneed++;
                if (!((xtempi < 0) || (xneed >= (curImage->width()))
                    || (ytempi < 0) || (yneed >= (curImage->height()))))
                {
                    hdr = xtemp - xtempi;
                    wdr = ytemp - ytempi;
                    red = (1 - wdr) * (1 - hdr) *  qRed(curImage->pixel(xtempi,ytempi))
                     + wdr * (1 - hdr) * qRed(curImage->pixel(xtempi,yneed))
                     + wdr * hdr * qRed(curImage->pixel(xneed,yneed))
                     + (1 - wdr) * hdr * qRed(curImage->pixel(xneed,ytempi));
                    green = (1 - wdr) * (1 - hdr) *  qGreen(curImage->pixel(xtempi,ytempi))
                     + wdr * (1 - hdr) * qGreen(curImage->pixel(xtempi,yneed))
                     + wdr * hdr * qGreen(curImage->pixel(xneed,yneed))
                     + (1 - wdr) * hdr * qGreen(curImage->pixel(xneed ,ytempi));
                    blue = (1 - wdr) * (1 - hdr) *  qBlue(curImage->pixel(xtempi,ytempi))
                     + wdr * (1 - hdr) * qBlue(curImage->pixel(xtempi,yneed))
                     + wdr * hdr * qBlue(curImage->pixel(xneed,yneed))
                     + (1 - wdr) * hdr * qBlue(curImage->pixel(xneed,ytempi));
                    Temp->setPixel(i,j,qRgb(red,green,blue));
                }
                else Temp->setPixel(i,j,qRgb(0,0,0));
            }
        }
        isModified = true;
        koefp = koef;
        *curImage = *Temp;
        image->convertFromImage(*curImage);
        delete Temp;
        statusBar()->showMessage(tr("Image was Zoomed"), 2000);
        repaint();
        return;
    }
    QMessageBox msgBox;
    msgBox.setText("Damn! You forgot to open an Image!!!");
    msgBox.exec();
    statusBar()->showMessage(r, 2000);
    return ;
}

void MainWindow::zoom2()//зум с изменением размера окна
{
    if (isOpened)
    {
        int koef = zoo;
        int hd, wd;
        int red,green,blue;
        QImage *Temp = new QImage(trunc(curImage->width() * koef/ 100),
                       trunc(curImage->height() * koef / 100),QImage::Format_RGB32);
        double hdr, wdr, tmpw, tmph;
        double tw = (float) (Temp->width() - 1) / (curImage->width() - 1);
        double th = (float) (Temp->height() - 1) / (curImage->height() - 1);
        for (int i = 0; i < (Temp->height()); i++)
        {
            tmph = (float) i / th;
            for (int j = 0; j < (Temp->width()); j++)
            {
                hd = trunc(tmph);
                if (hd < 0) hd = 0;
                else
                    if (hd >= curImage->height() - 1) hd = curImage->height() - 2;
                hdr = tmph - hd;
                tmpw = (float)j / tw;
                wd = trunc(tmpw);
                if (wd < 0) wd = 0;
                else
                    if (wd >= curImage->width() - 1) wd = curImage->width() - 2;
                wdr = tmpw - wd;
                red = (1 - wdr) * (1 - hdr) *  qRed(curImage->pixel(wd,hd))
                     + wdr * (1 - hdr) * qRed(curImage->pixel(wd,hd + 1))
                     + wdr * hdr * qRed(curImage->pixel(wd + 1,hd + 1))
                     + (1 - wdr) * hdr * qRed(curImage->pixel(wd + 1,hd));
                green = (1 - wdr) * (1 - hdr) *  qGreen(curImage->pixel(wd,hd))
                     + wdr * (1 - hdr) * qGreen(curImage->pixel(wd,hd + 1))
                     + wdr * hdr * qGreen(curImage->pixel(wd + 1,hd + 1))
                     + (1 - wdr) * hdr * qGreen(curImage->pixel(wd + 1,hd));
                blue = (1 - wdr) * (1 - hdr) *  qBlue(curImage->pixel(wd,hd))
                     + wdr * (1 - hdr) * qBlue(curImage->pixel(wd,hd + 1))
                     + wdr * hdr * qBlue(curImage->pixel(wd + 1,hd + 1))
                     + (1 - wdr) * hdr * qBlue(curImage->pixel(wd + 1,hd));
                Temp->setPixel(j,i,qRgb(red,green,blue));
            }
        }
        isModified = true;
        *curImage = *Temp;
        image->convertFromImage(*curImage);
        labelIm->setMinimumSize(curImage->width(), curImage->height());
        delete Temp;
        koefp = koef;
        statusBar()->showMessage(tr("Zoomed2"), 2000);
        repaint();
        return;
    }
    QMessageBox msgBox;
    msgBox.setText(tr("Damn! You forgot to open an Image!!!"));
    msgBox.exec();
    statusBar()->showMessage(r, 2000);
    return ;
}

void MainWindow::grayworld()
{
    if (isOpened)
    {
        long int red = 0 , green = 0 , blue = 0 , N = (curImage->width() * curImage->height());
        double redN = 0 , greenN = 0 , blueN = 0, midN;
        QImage *Temp = new QImage(curImage->width(),curImage->height(),QImage::Format_RGB32);
        for (int i = 0; i < (Temp->width()); i++)
        {
            for (int j = 0; j < (Temp->height()); j++)
            {
                redN += (double)qRed(curImage->pixel(i,j)) / N;
                greenN += (double)qGreen(curImage->pixel(i,j)) / N;
                blueN += (double)qBlue(curImage->pixel(i,j)) / N;
            }
        }
        midN = (float)(redN + greenN + blueN) / 3;
        for (int i = 0; i < (Temp->width()); i++)
        {
            for (int j = 0; j < (Temp->height()); j++)
            {
                red = (double)qRed(curImage->pixel(i,j)) * midN / redN;
                green = (double)qGreen(curImage->pixel(i,j)) * midN / greenN;
                blue = (double)qBlue(curImage->pixel(i,j)) * midN / blueN;
                if (red > 255) red = 255;
                if (green > 255) green = 255 ;
                if (blue > 255) blue = 255;
                Temp->setPixel(i , j , qRgb(red, green, blue));
            }
        }
        isModified = true;
        *curImage = *Temp;
        image->convertFromImage(*curImage);
        delete Temp;
        statusBar()->showMessage(tr("Image was Gray Worlded"), 2000);
        repaint();
        return;
    }
    QMessageBox msgBox;
    msgBox.setText(tr("Damn! You forgot to open an Image!!!"));
    msgBox.exec();
    statusBar()->showMessage(r, 2000);
    return ;
}

void MainWindow::waves()//Поперечно-продольные волны))
{
    if (isOpened)
    {
        double dl = wadl;
        double amp = waam;
        double xtemp, ytemp;
        int xneed, yneed, xtempi, ytempi;
        int red,green,blue;
        QImage *Temp = new QImage(curImage->width(),curImage->height(),QImage::Format_RGB32);
        double hdr, wdr;
        for (int i = 0; i < (Temp->width()); i++)
        {
            for (int j = 0; j < (Temp->height()); j++)
            {
                xtemp = i + amp * sin(2 * i * asin(1) / dl);
                ytemp = j + amp * sin(2 * j * asin(1) / dl);
                xtempi = (int) trunc(xtemp);
                xneed = xtempi;
                if (xtemp != xtempi)
                    xneed++;
                ytempi = (int) trunc(ytemp);
                yneed = ytempi;
                if (ytemp != ytempi)
                    yneed++;
                if (!((xtempi < 0) || (xneed >= curImage->width())
                   || (ytempi < 0) || (yneed >= curImage->height())))
                {
                    hdr = xtemp - xtempi;
                    wdr = ytemp - ytempi;
                    red = (1 - wdr) * (1 - hdr) *  qRed(curImage->pixel(xtempi,ytempi))
                        + wdr * (1 - hdr) * qRed(curImage->pixel(xtempi,yneed))
                        + wdr * hdr * qRed(curImage->pixel(xneed,yneed))
                        + (1 - wdr) * hdr * qRed(curImage->pixel(xneed,ytempi));
                    green = (1 - wdr) * (1 - hdr) *  qGreen(curImage->pixel(xtempi,ytempi))
                        + wdr * (1 - hdr) * qGreen(curImage->pixel(xtempi,yneed))
                        + wdr * hdr * qGreen(curImage->pixel(xneed,yneed))
                        + (1 - wdr) * hdr * qGreen(curImage->pixel(xneed ,ytempi));
                    blue = (1 - wdr) * (1 - hdr) *  qBlue(curImage->pixel(xtempi,ytempi))
                        + wdr * (1 - hdr) * qBlue(curImage->pixel(xtempi,yneed))
                        + wdr * hdr * qBlue(curImage->pixel(xneed,yneed))
                        + (1 - wdr) * hdr * qBlue(curImage->pixel(xneed,ytempi));
                    Temp->setPixel(i,j,qRgb(red,green,blue));
                }
                else Temp->setPixel(i,j,qRgb(0,0,0));
            }
        }
        isModified = true;
        *curImage = *Temp;
        image->convertFromImage(*curImage);
        delete Temp;
        statusBar()->showMessage(tr("Image was Waved"), 2000);
        repaint();
        return;
    }
    QMessageBox msgBox;
    msgBox.setText(tr("Damn! You forgot to open an Image!!!"));
    msgBox.exec();
    statusBar()->showMessage(r, 2000);
    return ;
}

void MainWindow::harshnes()
{
    if (isOpened)
    {
        double koef = sha;
        int red,green,blue;
        QImage *Temp = new QImage(*curImage);
        inputgau(0.7);
        gauss();
        /*for (int i = 0; i < (Temp->width()); i++)// это для просмотра контура
          {
             for (int j = 0; j < (Temp->height()); j++)
             {
                red = round(qRed(Temp->pixel(i,j)) - qRed(curImage->pixel(i,j)));
                green = round(qGreen(Temp->pixel(i,j)) - qGreen(curImage->pixel(i,j)));
                blue = round(qBlue(Temp->pixel(i,j)) - qBlue(curImage->pixel(i,j)));
                Temp->setPixel(i , j , qRgb(red, green, blue));
             }
          }*/
        for (int i = 0; i < (Temp->width()); i++)
        {
            for (int j = 0; j < (Temp->height()); j++)
            {
                red = round(qRed(Temp->pixel(i,j)) + koef * (qRed(Temp->pixel(i,j)) - qRed(curImage->pixel(i,j))));
                green = round(qGreen(Temp->pixel(i,j)) + koef * (qGreen(Temp->pixel(i,j)) - qGreen(curImage->pixel(i,j))));
                blue = round(qBlue(Temp->pixel(i,j)) + koef * (qBlue(Temp->pixel(i,j)) - qBlue(curImage->pixel(i,j))));
                if (red > 255) red = 255;
                if (green > 255) green = 255;
                if (blue > 255) blue = 255;
                Temp->setPixel(i , j , qRgb(red, green, blue));
            }
        }
        isModified = true;
        *curImage = *Temp;
        image->convertFromImage(*curImage);
        delete Temp;
        statusBar()->showMessage(tr("Image was Sharped"), 2000);
        repaint();
        return;
    }
    QMessageBox msgBox;
    msgBox.setText(tr("Damn! You forgot to open an Image!!!"));
    msgBox.exec();
    statusBar()->showMessage(r, 2000);
    return ;
}

void MainWindow::linear()//линейное растяжение гистограммы
{
    if (isOpened)
    {
        QImage *Temp = new QImage(curImage->width(),curImage->height(),
                                  QImage::Format_RGB32);
        extension(Temp, 0);
        isModified = true;
        image->convertFromImage(*curImage);
        labelIm->setMinimumSize(curImage->width(), curImage->height());
        delete Temp;
        statusBar()->showMessage(tr("Image was Lineal Extensioned"), 2000);
        repaint();
        return;
    }
    QMessageBox msgBox;
    msgBox.setText("Damn! You forgot to open an Image!!!");
    msgBox.exec();
    statusBar()->showMessage(r, 2000);
    return;
}
void MainWindow::inchannel()//поканальное растяжение гистограммы
{
    int i;

    if (isOpened)
    {
        QImage *Temp = new QImage(curImage->width(),curImage->height(),QImage::Format_RGB32);
        for (i = 1; i < 4; i++)
            extension(Temp, i);
        isModified = true;
        image->convertFromImage(*curImage);
        labelIm->setMinimumSize(curImage->width(), curImage->height());
        delete Temp;
        statusBar()->showMessage(tr("Image was Channel Extensioned"), 2000);
        repaint();
        return;
    }
    QMessageBox msgBox;
    msgBox.setText("Damn! You forgot to open an Image!!!");
    msgBox.exec();
    statusBar()->showMessage(r, 2000);
    return;
}
void MainWindow::extension(QImage *Temp, const int channels)//растяжение гистограммы
{
     int i , j , min , max , tmp2;
     int red , green , blue;
     double tmp1, tmp3, tmp4, tmp5;
     int *hist = new int[256];

     for (i = 0; i < 256; i++) hist[i] = 0;
     for (i = 0; i < curImage->height(); i++)
         for (j = 0; j < curImage->width(); j++)
             switch (channels)
             {
                case 3:
                {
                    hist[qRed(curImage->pixel(j , i))]++;
                    break;
                }
                case 2:
                {
                    hist[qGreen(curImage->pixel(j , i))]++;
                    break;
                }
                case 1:
                {
                    hist[qBlue(curImage->pixel(j , i))]++;
                    break;
                }
                case 0:
                {
                    tmp2 =(int)round(0.2125 * qRed(curImage->pixel(j , i)) + 0.7154 * qGreen(curImage->pixel(j , i)) + 0.0721 * qBlue(curImage->pixel(j , i)));
                    hist[tmp2]++;
                }
            }
    int k = 0;
    while (!hist[k]) k++;
    min = k;
    k = 255;
    while (!hist[k]) k--;
    max = k;
    delete[] hist;
    tmp1 = (float)255 / (max - min);
    for (i = 0; i < curImage->height(); i++)
        for (j = 0; j < curImage->width(); j++)
        {
            red = qRed(curImage->pixel(j, i))  ;
            green = qGreen(curImage->pixel(j, i))  ;
            blue = qBlue(curImage->pixel(j, i))  ;
            tmp3 = ((red - min) * tmp1);
            if  (tmp3 > 255) tmp3 = 255;
            tmp4 = ((green - min) * tmp1);
            if  (tmp4 > 255) tmp4 = 255;
            tmp5 = ((blue - min) * tmp1);
            if  (tmp5 > 255) tmp5 = 255;
            switch (channels)
            {
                case 3:
                {
                    Temp->setPixel(j , i , qRgb( tmp3 , green, blue));
                    break;
                }
                case 2:
                {
                    Temp->setPixel(j , i , qRgb( red, tmp4 , blue ));
                    break;
                }
                case 1:
                {
                    Temp->setPixel(j , i , qRgb( red, green, tmp5 ));
                    break;
                }
                case 0:
                {
                    Temp->setPixel(j , i , qRgb( tmp3 , tmp4 , tmp5 ));
                }
            }
        }
    *curImage = *Temp;
}

void MainWindow::median()//медианная фильтрация
    {
    if (isOpened)
    {
        int size = med;
        double tem;
        int ost = (size - 1) / 2;
        int i , j , k , l , n, temi, temj;
        double filtr[(size * size)];
        int filtri[(size * size)];
        int filtrj[(size * size)];
        QImage *Temp = new QImage(curImage->width(),curImage->height(),QImage::Format_RGB32);
        for (i = ost; i < curImage->width() - ost; i++)
            for (j = ost; j < curImage->height() - ost; j++)
            {
                for (k = (-ost) ; k <= ost ; k++)
                    for (l = (-ost) ; l <= ost ; l++)
                    {
                        if (( (i + k) >= 0) && ( (i + k) < curImage->width()) && ( (j + l) >= 0 ) && ( (j + l) < curImage->height()))
                            filtr[((k + ost) * size + (l + ost))] =
                                round(0.2125 * qRed(curImage->pixel((i + k) , (j + l)))
                                + 0.7154 * qGreen(curImage->pixel((i + k) , (j + l)))
                                + 0.0721 * qBlue(curImage->pixel((i + k) , (j + l))));
                        else
                            filtr[((k + ost) * size + (l + ost))] = 0;
                        filtri[((k + ost) * size + (l + ost))] = (i + k);
                        filtrj[((k + ost) * size + (l + ost))] = (j + l);
                    }
                for (int k = 0; k < (size * size) - 1; k++)// сорт
                {
                    n = k;
                    tem = filtr[k];
                    temi = filtri[k];
                    temj = filtrj[k];
                    for (l = k; l < (size * size); l++)
                    {
                        if (filtr[l] < tem)
                        {
                            n = l;
                            tem = filtr[l];
                            temi = filtri[l];
                            temj = filtrj[l];
                        }
                    }
                    filtr[n] = filtr[k];
                    filtri[n] = filtri[k];
                    filtrj[n] = filtrj[k];
                    filtr[k] = tem;
                    filtri[k] = temi;
                    filtrj[k] = temj;
                }
                tem = filtr[((size * size) - 1) / 2];
                temi = filtri[((size * size) - 1) / 2];
                temj = filtrj[((size * size) - 1) / 2];
                Temp->setPixel(i , j , curImage->pixel(temi, temj));
        }
        *curImage = *Temp;
        isModified = true;
        image->convertFromImage(*curImage);
        delete Temp;
        statusBar()->showMessage(tr("Image was Medianed"), 2000);
        repaint();
        return;
    }
    QMessageBox msgBox;
    msgBox.setText("Damn! You forgot to open an Image!!!");
    msgBox.exec();
    statusBar()->showMessage(r, 2000);
    return ;
}

void MainWindow::gauss()//сепарабельное размытие
{
    if (isOpened)
    {
        double sigma = gau;
        int N = 1 + (float)(3 * sigma), i;
        double tem;
        double wind[(2 * N) + 1];
        QImage *Temp = new QImage(curImage->width(),curImage->height(),QImage::Format_RGB32);
        for (i = (2 * N); i >= 0; i--)
        {
            if (i >= N)
            {
                tem = (float)(N - i) * (i - N) / (2 * sigma * sigma);
                if (tem >= 0)
                    wind[i]= exp(tem);
                else
                    wind[i]= 1 / exp(-tem);
            }
            else wind[i] = wind[2 * N - i] ;
        }
        wash(Temp, curImage->height(), curImage->width(), N, wind, true);
        wash(Temp, curImage->width(), curImage->height(), N, wind , false);
        isModified = true;
        image->convertFromImage(*curImage);
        delete Temp;
        statusBar()->showMessage(tr("Image was Gaussed"), 2000);
        repaint();
        return;
    }
    QMessageBox msgBox;
    msgBox.setText("Damn! You forgot to open an Image!!!");
    msgBox.exec();
    statusBar()->showMessage(r, 2000);
    return ;
}
void MainWindow::wash(QImage *Temp,int koef1, int koef2, int N, double* wind, bool a)//размытие
{
    int i , j , k;
    double red, green, blue;
    double sum;
    for (i = 0; i < koef1; i++)
        for (j = 0; j < koef2; j++)
        {
            sum = 0;
            red = 0;
            green = 0;
            blue = 0;
            for (k = (-N) ; k <= N ; k++)
                if (( (j + k) >= 0) && ( (j + k) < koef2))
                {
                    if (a)
                    {
                        red += qRed(curImage->pixel(j + k, i)) * wind [k + N] ;
                        green += qGreen(curImage->pixel(j + k, i)) * wind [k + N] ;
                        blue += qBlue(curImage->pixel(j + k, i)) * wind [k + N] ;
                    }
                    else
                    {
                        red += qRed(curImage->pixel(i, j + k)) * wind [k + N] ;
                        green += qGreen(curImage->pixel(i, j + k)) * wind [k + N] ;
                        blue += qBlue(curImage->pixel(i, j + k)) * wind [k + N] ;
                    }
                }
            for (k = (-N) ; k <= N ; k++) if (( (j + k) >= 0) && ( (j + k) < koef2))
                sum += wind[k + N];
            if (a)
                Temp->setPixel(j , i , qRgb(red / sum, green / sum, blue / sum));
            else
                Temp->setPixel(i , j , qRgb(red / sum, green / sum, blue / sum));
        }
    *curImage = *Temp;
}

void MainWindow::rotate()//поворот; 0' - самое начальное положение
{
    if (isOpened)
    {
        double koef = rot;
        double k = koef - koefg;
        double rCos = cos(k * (asin(1) / 90)), rSin = sin(k * asin(1) / 90), xtemp, ytemp;
        int xneed, yneed, xtempi, ytempi;
        int red,green,blue;
        QImage *Temp = new QImage(curImage->width(),curImage->height(),QImage::Format_RGB32);
        double hdr, wdr;
        int crotx = (curImage->width() - 1) / 2, croty = (curImage->height() - 1) / 2;
        for (int i = 0; i < (Temp->width()); i++)
        {
            for (int j = 0; j < (Temp->height()); j++)
            {
                if ( (i == crotx)&&(j == croty) )
                {
                    Temp->setPixel(i,j,curImage->pixel(i,j));
                    continue;
                }
                xtemp = (i - crotx) * rCos - (croty - j) * rSin + crotx;
                ytemp = croty - (i - crotx) * rSin - (croty - j) * rCos;
                xtempi = (int) trunc(xtemp);
                xneed = xtempi;
                if (xtemp != xtempi)
                    xneed++;
                ytempi = (int)trunc(ytemp);
                yneed = ytempi;
                if (ytemp != ytempi)
                    yneed++;
                if (!((xtempi < 0) || (xneed >= curImage->width()) || (ytempi < 0) || (yneed >= curImage->height())))
                {
                    hdr = xtemp - xtempi;
                    wdr = ytemp - ytempi;
                    red = (1 - wdr) * (1 - hdr) *  qRed(curImage->pixel(xtempi,ytempi))
                        + wdr * (1 - hdr) * qRed(curImage->pixel(xtempi,yneed))
                        + wdr * hdr * qRed(curImage->pixel(xneed,yneed))
                        + (1 - wdr) * hdr * qRed(curImage->pixel(xneed,ytempi));
                    green = (1 - wdr) * (1 - hdr) *  qGreen(curImage->pixel(xtempi,ytempi))
                        + wdr * (1 - hdr) * qGreen(curImage->pixel(xtempi,yneed))
                        + wdr * hdr * qGreen(curImage->pixel(xneed,yneed))
                        + (1 - wdr) * hdr * qGreen(curImage->pixel(xneed ,ytempi));
                    blue = (1 - wdr) * (1 - hdr) *  qBlue(curImage->pixel(xtempi,ytempi))
                        + wdr * (1 - hdr) * qBlue(curImage->pixel(xtempi,yneed))
                        + wdr * hdr * qBlue(curImage->pixel(xneed,yneed))
                        + (1 - wdr) * hdr * qBlue(curImage->pixel(xneed,ytempi));
                    Temp->setPixel(i,j,qRgb(red,green,blue));
                }
                else Temp->setPixel(i,j,qRgb(0,0,0));
            }
        }
        isModified = true;
        *curImage = *Temp;
        image->convertFromImage(*curImage);
        delete Temp;
        koefg = koef;
        statusBar()->showMessage(tr("Image was Rotated"), 2000);
        repaint();
        return;
    }
    QMessageBox msgBox;
    msgBox.setText(tr("Damn! You forgot to open an Image!!!"));
    msgBox.exec();
    statusBar()->showMessage(r, 2000);
    return ;
}


void MainWindow::createActions()
{

    openImAct = new QAction(tr("&Open..."), this);
    openImAct->setShortcuts(QKeySequence::Open);
    openImAct->setStatusTip(tr("Open an existing IMAGE"));
    connect(openImAct, SIGNAL(triggered()), this, SLOT(openIm()));

    saveImAct = new QAction(tr("&Save"), this);
    saveImAct->setShortcuts(QKeySequence::Save);
    saveImAct->setStatusTip(tr("Save the Image to disk"));
    connect(saveImAct, SIGNAL(triggered()), this, SLOT(saveIm()));

    saveImAsAct = new QAction(tr("Save &As..."), this);
    saveImAsAct->setShortcuts(QKeySequence::SaveAs);
    saveImAsAct->setStatusTip(tr("Save the Image under to disk a new name"));
    connect(saveImAsAct, SIGNAL(triggered()), this, SLOT(saveImAs()));

    exitAct = new QAction(tr("E&xit"), this);
    exitAct->setShortcuts(QKeySequence::Quit);
    exitAct->setStatusTip(tr("Exit poorPaint"));
    connect(exitAct, SIGNAL(triggered()), this, SLOT(exit()));

    zoomAct = new QAction(this);
    zoomAct->setStatusTip(tr("Zoom"));
    connect(spinBoxG2, SIGNAL(valueChanged(double)), this, SLOT(inputzoo(double)));
    connect(butG2, SIGNAL(pressed()), this, SLOT(zoom()));

    zoom2Act = new QAction(this);
    zoom2Act->setStatusTip(tr("Zoom2"));
    connect(spinBoxG, SIGNAL(valueChanged(double)), this, SLOT(inputzoo(double)));
    connect(butG, SIGNAL(pressed()), this, SLOT(zoom2()));

    rotationAct = new QAction(this);
    rotationAct->setStatusTip(tr("Rotation"));
    connect(spinBoxG1, SIGNAL(valueChanged(double)), this, SLOT(inputrot(double)));
    connect(butG1, SIGNAL(pressed()), this, SLOT(rotate()));

    gaussAct = new QAction(this);
    gaussAct->setStatusTip(tr("Gauss"));
    connect(spinBoxF1, SIGNAL(valueChanged(double)), this, SLOT(inputgau(double)));
    connect(butF1, SIGNAL(pressed()), this, SLOT(gauss()));

    linearAct = new QAction(tr("&Linear"),this);
    linearAct->setStatusTip(tr("Linear Extension"));
    connect(linearAct, SIGNAL(triggered()), this, SLOT(linear()));

    channelAct = new QAction(tr("&Channel"),this);
    channelAct->setStatusTip(tr("Channel Extension"));
    connect(channelAct, SIGNAL(triggered()), this, SLOT(inchannel()));

    harshnessAct = new QAction(this);
    harshnessAct->setStatusTip(tr("Harshness"));
    connect(spinBoxH, SIGNAL(valueChanged(double)), this, SLOT(inputsha(double)));
    connect(butH, SIGNAL(pressed()), this, SLOT(harshnes()));

    wavesAct = new QAction(this);
    wavesAct->setStatusTip(tr("Waves"));
    connect(spinBoxW1, SIGNAL(valueChanged(double)), this, SLOT(inputwadl(double)));
    connect(spinBoxW2, SIGNAL(valueChanged(double)), this, SLOT(inputwaam(double)));
    connect(butW, SIGNAL(pressed()), this, SLOT(waves()));

    medianAct = new QAction(this);
    medianAct->setStatusTip(tr("Median"));
    connect(spinBoxM, SIGNAL(valueChanged(int)), this, SLOT(inputmed(int)));
    connect(butM, SIGNAL(pressed()), this, SLOT(median()));

    grayworldAct = new QAction(tr("&Gray World"), this);
    grayworldAct->setStatusTip(tr("Gray World"));
    connect(grayworldAct, SIGNAL(triggered()), this, SLOT(grayworld()));

}


void MainWindow::createMenus()
{

    fileMenu = menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(openImAct);
    fileMenu->addAction(saveImAct);
    fileMenu->addAction(saveImAsAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);

    effectsMenu = menuBar()->addMenu(tr("&Effects"));
    effectsMenu->addAction(linearAct);
    effectsMenu->addAction(channelAct);
    effectsMenu->addAction(grayworldAct);

    menuBar()->addSeparator();

}

void MainWindow::inputmed(int b)
{
    med = b;
}
void MainWindow::inputgau(const double a)
{
    gau = a;
}
void MainWindow::inputsha(const double a)
{
    sha = a;
}
void MainWindow::inputzoo(const double a)
{
    zoo = a;
}
void MainWindow::inputrot(const double a)
{
    rot = a;
}
void MainWindow::inputwaam(const double a)
{
    waam = a;
}
void MainWindow::inputwadl(const double a)
{
    wadl = a;
}

void MainWindow::createStatusBar()
{
    statusBar()->showMessage(tr("Ready"));
}

bool MainWindow::maybeSave()
{

    QMessageBox msgBox;
    msgBox.setText("The document has been modified.");
    msgBox.setInformativeText("Do you want to save your changes?");
    msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::SaveAll
                              | QMessageBox::Discard | QMessageBox::Cancel);
    msgBox.setDefaultButton(QMessageBox::Save);
    int ret = msgBox.exec();
    switch (ret)
    {
        case QMessageBox::Save:
        {
            isModified = false;
            saveIm();
            return true;
        }
        case QMessageBox::SaveAll:
        {
            isModified = false;
            saveImAs();
            return true;
        }
        case QMessageBox::Discard:
        {
            return true;
        }
        case QMessageBox::Cancel:
        {
        }
    }
    return false;
}
