#include "visualdetectwidget.h"
#include "ui_visualdetectwidget.h"

VisualDetectWidget::VisualDetectWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::VisualDetectWidget)
{
    ui->setupUi(this);
    setWindowFlags (Qt::Window | Qt::FramelessWindowHint);
    setWindowModality(Qt::ApplicationModal);

    initialize();
    initControl();

    m_imgPath = "";
    m_globalFlag = 0; //定义全局变量标志位；
    grayScale(); //灰度化与二值化；
    //on_buttonLoadImage_clicked();//加载图片；
}

VisualDetectWidget::~VisualDetectWidget()
{
    delete ui;
}

void VisualDetectWidget::initialize()
{

}

void VisualDetectWidget::initControl()
{
    //根据不同分辨率设置控件的位置和尺寸
    switch (g_emResolut)
    {
    case resolution1910:
        initResolution1910();
        break;
    case resolution1006:
        this->resize(1024,600);
        break;
    default:
        initResolution1910();
        break;
    }

    initControlStyle();//初始化窗体控件样式
}

void VisualDetectWidget::initResolution1910()
{
    this->resize(600,680);
    this->move((1920-this->width())/2,(1080-this->height())/2);

    ui->labelImage->setGeometry(20,20,560,560);
    ui->framePageBtn->setGeometry(422,610,168,70);
    ui->buttonBack->setGeometry(0,0,168,70);
}

void VisualDetectWidget::initControlStyle()
{
    SetControlStyle setControlStyle;
    setControlStyle.setUiName(this->objectName());

    ui->buttonBack->setBottomImage(setControlStyle.getSharedBottomStyleSheet(ui->buttonBack->parent()->objectName()));
    ui->buttonBack->setTopImage(setControlStyle.getSharedTopStyleSheet(ui->buttonBack->objectName()));
}

#if(0)
void VisualDetectWidget::loadVisualDetectImage()
{
    QDir apppath(qApp->applicationDirPath());
    QString ImagePath = apppath.path() + apppath.separator() + "Image.png";

    QImage image;
    image.load(ImagePath);
    QPixmap pix = QPixmap::fromImage(image);
    ui->labelImage->setPixmap(pix);

#ifdef Q_OS_WIN
    int x = image.width();
    int y = image.height();
    std::vector<QRgb> v1(x,1);
    std::vector<std::vector<QRgb>> v2(y,v1);

    for(int i = 0; i < y; i++)
    {
        for(int j = 0; j < x; j++)
        {
            QRgb pixel = image.pixel(j,i);
            v2[i][j] = pixel;
        }
    }
#endif
}
#endif

//将彩色图片转换为黑白图片；
void VisualDetectWidget::grayScale()
{
    QDir apppath(qApp->applicationDirPath());
    QString path = apppath.path() + apppath.separator() + "Photograph" + apppath.separator() + "image.jpg";

    QFile imgFile(path);
    if(!imgFile.exists())//不存在照片
    {
        return;
    }

    QImage *img = new QImage();
    img->load(path);

    unsigned int * data = (unsigned int *)img->bits();

    int size = img->width()*img->height();
    int red;
    int green;
    int blue;

    for(int i = 0; i < size; i++)
    {
        red = qRed(data[i]) * 0.3;
        green = qGreen(data[i]) * 0.59;
        blue = qBlue(data[i]) * 0.11;

        int rgb = red + green + blue;

        if(rgb > 80)
        {
            rgb = 255;
        }
        else
        {
            rgb =0;
        }
        data[i] = qRgba(rgb,rgb,rgb,qAlpha(data[i]));
    }

    QString pathSave = apppath.path() + apppath.separator() + "images_save.png";
    m_imgPath = pathSave;
    img->save(pathSave);//保存二值化后的图片；

    QImage *image = new QImage();
    image->load(pathSave);
    int width = image->width();
    int height = image->height();

    int labelWidth = ui->labelImage->width();
    int labelHeight = ui->labelImage->height();

    int imgWidth = 0;
    int imgHeight = 0;

    float labelScale = (labelWidth *1.0)/(labelHeight*1.0);
    float pictureScale = (width *1.0)/(height *1.0);
    qDebug()<<labelScale<<"labelScale"<< pictureScale<<"pictureScale";

    if(labelScale > pictureScale)
    {
        imgHeight = labelHeight;
        imgWidth = labelHeight * pictureScale;
    }
    else
    {
        imgWidth = labelWidth;
        imgHeight = labelWidth / pictureScale;
    }

    QPixmap *pixmap = new QPixmap;
    QPixmap pix = pixmap->fromImage(*image);

    pix= pix.scaled(imgWidth,imgHeight);
    ui->labelImage->setPixmap(pix);
    m_globalFlag =1;//灰度化转换完成
}

void VisualDetectWidget::on_buttonBack_clicked()
{
    this->close();
}

//加载图片功能；
void VisualDetectWidget::on_buttonLoadImage_clicked()
{
    QString path = QFileDialog::getOpenFileName(this,tr("Select file"),"D:",tr("PNG(*.png)"));
    m_imgPath = path;
    QImage *image = new QImage();
    image->load(path);

    int width = image->width();
    int height = image->height();

    int labelWidth = ui->labelImage->width();
    int labelHeight = ui->labelImage->height();

    int imgWidth = 0;
    int imgHeight = 0;

    float labelScale = (labelWidth * 1.0) / (labelHeight * 1.0);
    float pictureScale = (width * 1.0) / (height * 1.0);

    if(labelScale > pictureScale)
    {
        imgHeight = labelHeight;
        imgWidth = labelHeight * pictureScale;
    }
    else
    {
        imgWidth = labelWidth;
        imgHeight = labelWidth / pictureScale;
    }

    QPixmap *pixmap= new QPixmap;
    QPixmap pp= pixmap->fromImage(*image);

    pp = pp.scaled(imgWidth,imgHeight);
    ui->labelImage->setPixmap(pp);
    m_globalFlag =1;
}

//识别点的个数；
void VisualDetectWidget::on_buttonGetPointNumber_clicked()
{
    //获取给定的最大与最小的个数；
    QString  str = ui->lineEdit_maxNumber->text();
    int maxCount = str.toInt();
    QString str2 = ui->lineEdit_minNumber->text();
    int minCount = str2.toInt();
    QString outStr;
    //对话框；
    QMessageBox *box  = new QMessageBox();
    //1.判断用户是否已经加载了图片；
    if(m_globalFlag == 0)
    {
        outStr = "请先加载图片";
        box->information(this,"错误",outStr);
    }
    else
    {
        //判断用户是否填写输入框；
        //1）将字符串转化为列表；
        QStringList list1 = str.split("");
        QStringList list2 = str2.split("");

        //2)判断列表是否为空；
        if(list1.size() == 2 || list2.size() == 2)
        {
            //弹出对话框，提示“请输入最大与最小值”
            outStr = "输入框为空，请输入最大与最小值";
            box->information(this,"错误",outStr);
        }
        else
        {
            //循环遍历列表，判断数值是否在0~9之间，如不在，弹出提示框；若在，则进行判断点的识别；
            //循环判断第一个输入框的列表；
            for(int i = 1; i < list1.size() - 1; i++)
            {
                QString tmp = list1.at(i);
                qDebug()<<"tmp="<<tmp;
                if(tmp < "0" || tmp > "9")
                {
                    //提示请在输入框1中输入在0~9之间的数字；
                    //qDebug()<<"please input number from 0 to9 in lineEdit1";
                    outStr = "最大最小值输入错误";
                    box->information(this,"错误",outStr);
                    return;
                }
            }
            //循环判断第二个输入框的列表；
            for(int j = 1; j < list2.size() - 1; j++)
            {
                QString tmp2 = list2.at(j);
                qDebug()<<"tmp2"<<tmp2;
                if(tmp2 < "0" || tmp2 > "9")
                {
                    //提示请在输入框2中输入在0~9之间的数字；
                    //qDebug()<<"please input number from 0 to9 in lineEdit2";
                    outStr = "最大最小值输入错误";
                    box->information(this,"错误",outStr);
                    return;
                }
            }
            //----------------------进行判断点的识别-----------------------；

            //获取原图像；
            QString path = m_imgPath ;
            QImage *image = new QImage();
            image->load(path);

            //1.获取图像像素字节数据的首地址 ---将二值化图像转换为数组
            unsigned int *data = (unsigned int *)image->bits();

            int width =image->width();//图像宽；
            int height = image->height();//图像高；

            int red;
            int green;
            int blue;

            int pointHeight = 0;
            int pointWidth = 0;

            int pointNum = 0;

            int size = width * (height - 12);//获取数组的个数；

            for(int i = 1; i < size; i++)
            {
                red = qRed(data[i]);
                green = qGreen(data[i]);
                blue = qBlue(data[i]);

                //判断该像素 是否是合格点的第一个像素,符合才需要进行宽与高的计算；
                if(red == 255 && green == 255 && blue == 255)
                {
                    int frontRed = qRed(data[i-1]);
                    int frontGreen = qGreen(data[i-1]);
                    int frontBlue = qBlue(data[i-1]);
                    //判断该像素的前一个像素是否为黑色；
                    if(frontRed == 0 && frontGreen == 0 && frontBlue == 0)
                    {
                        int temp = i;
                        //qDebug()<<temp<<"white";
                        int flag = 1;
                        //判断该像素的上面的7个像素是否为连续黑色；
                        for(int j = 0; j < 7; j++)
                        {
                            int upRed = qRed(data[temp - width + j]);
                            int upGreen = qGreen(data[temp - width + j]);
                            int upBlue = qBlue(data[temp - width + j]);
                            if(upRed == 255 && upGreen == 255 && upBlue == 255)
                            {
                                flag = 0;
                                break;
                                //qDebug()<<"该像素上面的7个点不是连续的black,第"<<temp-width+j<<"is white";
                            }
                        }

                        //如果这七个像素都为黑色，则计算该点的宽与高；
                        if(flag)
                        {
                            //qDebug()<<"maybe a point";
                            //判断该像素 后面的几个像素是否为白色，如果是白色，记录个数；
                            int tempNum = 0;
                            tempNum = temp;

                            int nextRed = qRed(data[tempNum]);
                            int nextGreen = qGreen(data[tempNum]);
                            int nextBlue = qBlue(data[tempNum]);
                            while(nextRed == 255 && nextGreen == 255 && nextBlue == 255)
                            {
                                tempNum++;
                                nextRed = qRed(data[tempNum]);
                                nextGreen = qGreen(data[tempNum]);
                                nextBlue = qBlue(data[tempNum]);
                            }
                            int count;
                            count = tempNum - temp;
                            //qDebug()<<count<<"count";

                            int midNum = 0;
                            int midNumber = 0;
                            int tempMid = 0;

                            int bottomRed;
                            int bottomGreen;
                            int bottomBlue;

                            //计算中间值；
                            if(count % 2 != 0)
                            {
                                //如果是奇数；
                                midNum = (temp + tempNum - 1) / 2;//计算出中间值的坐标

                                //计算该列有多高；
                                int m = 1;
                                bottomRed = qRed(data[midNum + width]);
                                bottomGreen = qRed(data[midNum + width]);
                                bottomBlue = qRed(data[midNum + width]);
                                while(bottomRed == 255 && bottomGreen == 255 && bottomBlue == 255)
                                {
                                    m++;
                                    bottomRed = qRed(data[midNum + m * width]);
                                    bottomGreen = qRed(data[midNum + m * width]);
                                    bottomBlue = qRed(data[midNum + m * width]);
                                }
                                //高则为m的值；
                                pointHeight = m;
                                tempMid = midNum;
                            }
                            else
                            {
                                //如果是偶数；
                                midNum = (temp + tempNum - 1) / 2;
                                midNumber = midNum + 1;

                                //需要计算出这两列的高；
                                int n = 1;
                                bottomRed = qRed(data[midNum + width]);
                                bottomGreen = qRed(data[midNum + width]);
                                bottomBlue = qRed(data[midNum + width]);
                                while(bottomRed == 255 && bottomGreen == 255 && bottomBlue == 255)
                                {
                                    n++;
                                    bottomRed = qRed(data[midNum + n * width]);
                                    bottomGreen = qRed(data[midNum + n * width]);
                                    bottomBlue = qRed(data[midNum + n * width]);
                                }

                                int k = 1;
                                bottomRed = qRed(data[midNumber + width]);
                                bottomGreen = qRed(data[midNumber + width]);
                                bottomBlue = qRed(data[midNumber + width]);
                                while(bottomRed == 255 && bottomGreen == 255 && bottomBlue == 255)
                                {
                                    k++;
                                    bottomRed = qRed(data[midNumber + k * width]);
                                    bottomGreen = qRed(data[midNumber + k * width]);
                                    bottomBlue = qRed(data[midNumber + k * width]);
                                }
                                //                        qDebug()<<"n的值为："<<n;
                                //                        qDebug()<<"k的值为："<<k;
                                //比较这两者之间的大小；
                                if(n < k)
                                {
                                    pointHeight = k;
                                    tempMid = midNumber;
                                }
                                else if(n > k)
                                {
                                    pointHeight = n;
                                    tempMid = midNum;
                                }
                                else
                                {
                                    pointHeight = n;
                                    tempMid = midNum;
                                }
                            }

                            //对高取中间值，从而计算宽度；
                            int mid = 0;
                            int midFront = 0;
                            int countNum = 0;

                            int leftRed;
                            int leftGreen;
                            int leftBlue;

                            int rightRed;
                            int rightGreen;
                            int rightBlue;
                            if(pointHeight % 2 != 0)
                            {
                                //如果行高数为奇数
                                countNum = pointHeight / 2;
                                mid = midNum + countNum * width;
                                leftRed = qRed(data[mid]);
                                leftGreen = qGreen(data[mid]);
                                leftBlue = qBlue(data[mid]);

                                rightRed = qRed(data[mid]);
                                rightGreen = qGreen(data[mid]);
                                rightBlue = qBlue(data[mid]);

                                //根据中间坐标判断左右是否为白色，然后计算宽度；
                                int  k = 0;
                                //qDebug()<<"k的值为："<<k;
                                while(leftRed == 255 && leftGreen == 255 && leftBlue == 255)
                                {
                                    k++;
                                    leftRed = qRed(data[mid - k]);
                                    leftGreen = qGreen(data[mid - k]);
                                    leftBlue = qBlue(data[mid - k]);
                                }
                                //左侧的个数为k-1;
                                int m = 0;
                                while(rightRed == 255 && rightGreen == 255 && rightBlue == 255)
                                {
                                    m++;
                                    rightRed = qRed(data[mid + m]);
                                    rightGreen = qGreen(data[mid + m]);
                                    rightBlue = qBlue(data[mid + m]);
                                }
                                //右侧的个数为m+1;
                                //所以宽为左侧个数+1+右侧个数；
                                pointWidth = k + m + 1;
                            }
                            else
                            {
                                //如果高为偶数
                                countNum = pointHeight / 2;
                                mid = tempMid + countNum * width;
                                midFront = tempMid + (countNum - 1) * width;

                                leftRed = qRed(data[mid]);
                                leftGreen = qGreen(data[mid]);
                                leftBlue = qBlue(data[mid]);

                                rightRed = qRed(data[mid]);
                                rightGreen = qGreen(data[mid]);
                                rightBlue = qBlue(data[mid]);

                                //根据中间坐标判断左右是否为白色，然后计算宽度；
                                int temp_width = 0;
                                int temp_width2 = 0;
                                //1.判断左侧的个数
                                int  k = 0;
                                while(leftRed == 255 && leftGreen == 255 && leftBlue == 255)
                                {
                                    k++;
                                    leftRed = qRed(data[mid - k]);
                                    leftGreen = qGreen(data[mid - k]);
                                    leftBlue = qBlue(data[mid - k]);
                                }
                                //左侧的个数为k-1;

                                //2.判断右侧的个数；
                                int m = 0;
                                while(rightRed == 255 &&  rightGreen == 255 && rightBlue == 255)
                                {
                                    m++;
                                    rightRed = qRed(data[mid + m]);
                                    rightGreen = qGreen(data[mid + m]);
                                    rightBlue = qBlue(data[mid + m]);
                                }
                                //右侧的个数为m+1;
                                //所以宽为左侧个数+1+右侧个数；
                                temp_width = k + m + 1;
                                //qDebug()<<temp_width<<"temp_width";

                                //-----------------计算第一行的宽度------
                                leftRed = qRed(data[midFront]);
                                leftGreen = qGreen(data[midFront]);
                                leftBlue = qBlue(data[midFront]);

                                rightRed = qRed(data[midFront]);
                                rightGreen = qGreen(data[midFront]);
                                rightBlue = qBlue(data[midFront]);
                                //根据中间坐标判断左右是否为白色，然后计算宽度；
                                int  t = 0;
                                while(leftRed == 255 && leftGreen == 255 && leftBlue == 255)
                                {
                                    t++;
                                    leftRed = qRed(data[midFront - t]);
                                    leftGreen = qGreen(data[midFront - t]);
                                    leftBlue = qBlue(data[midFront - t]);
                                }
                                //左侧的个数为k-1;
                                int mm = 0;
                                while(rightRed == 255 &&  rightGreen == 255 && rightBlue == 255)
                                {
                                    mm++;
                                    rightRed = qRed(data[midFront + mm]);
                                    rightGreen = qGreen(data[midFront + mm]);
                                    rightBlue = qBlue(data[midFront + mm]);
                                }
                                //右侧的个数为m+1;
                                //所以宽为左侧个数+1+右侧个数；
                                temp_width2= t + mm + 1;
                                //qDebug()<<temp_width2<<"tempWidth2";

                                //比较这两者的大小；
                                int max;
                                if(temp_width < temp_width2)
                                {
                                    max = temp_width2;
                                }
                                else if(temp_width > temp_width2)
                                {
                                    max = temp_width;
                                }
                                else
                                {
                                    max = temp_width;
                                }

                                pointWidth = max;
                            }

                            //比较计算得到的最大高度与宽度 是否在给定的最大直径和最小直径；
                            if(pointHeight >= minCount && pointHeight <= maxCount)
                            {
                                if(pointWidth >= minCount && pointWidth <= maxCount)
                                {
                                    pointNum++;
                                }
                            }
                        }
                    }

                }
            }
            //将点的个数显示在对应的label中；
            ui->labelPointSum->setText(QString("%1").arg(pointNum));
        }
    }
}
