//
// Created by 阳坤 on 2022/2/23.
//

#include "image_blur_detection.h"


int image_blur_detection(const char *filename) {
    const char *temp_image_url = filename;
    cv::Mat cvImage = cv::imread(temp_image_url);
    return doDetection(cvImage);
}

int bytes_blur_detection(uint8_t *pData, int len) {
    cv::Mat img;
    std::vector<uchar> data;
    for (int i = 0; i < len; ++i) {
        data.push_back(pData[i]);
    }
    img = cv::imdecode(data, cv::IMREAD_COLOR);
    cv::flip(img, img, -1);
    img.channels();
    return doDetection(img);
}

int doDetection(cv::Mat cvImage) {
    //如果读入图像失败
    if (cvImage.empty()) {
        return -1;
    } else {
        cv::Mat grayCVImage;
        cv::cvtColor(cvImage, grayCVImage, cv::COLOR_BGR2GRAY);
        if (!grayCVImage.empty()) {
            cv::Mat laplacianImage;
            cv::Laplacian(grayCVImage, laplacianImage, CV_64F);
            cv::Scalar mu, sigma;
            cv::meanStdDev(laplacianImage, mu, sigma);
            int blur_value = sigma.val[0] * sigma.val[0];
            if (blur_value < DEFAULT_BLUR_THRESHOLD) {
                int color = image_color_ratio(grayCVImage);
                blur_value = color == 0 ? blur_value : color;
            }
            cvImage.release();
            grayCVImage.release();
            return blur_value;
        }
    }
    return -1;
}

//定义比较的函数
static bool cmp_value(const std::pair<long, long> left, const std::pair<long, long> right) {
    return left.second < right.second;
}

int image_color_ratio(cv::Mat image) {
    int num = 0;
    std::map<long, long> colors;
    for (int i = 0; i < image.rows; ++i) {
        for (int j = 0; j < image.cols; ++j) {
            int gray_data = image.at<uchar>(i, j);
            if (colors.count(gray_data) == 0) {
                colors[gray_data] = 1;
            } else {
                long a = ++colors[gray_data];
                colors[gray_data] = a;
            }
        }
    }
    if (!colors.empty()) {
        auto maxCount = 0L;
        if (colors.size() > 1) {
            maxCount = max_element(colors.begin(), colors.end(), cmp_value)->second;
        } else {
            std::map<long, long>::iterator iter;
            iter = colors.begin();
            while (iter != colors.end()) {
                maxCount = iter->second;
                break;
            }
        }
        float i = (float) maxCount / (float) (image.rows * image.cols);
        if (i >= DEFAULT_PIX_THRESHOLD) {
            num = DEFAULT_BLUR_THRESHOLD + 1;
        };
    }
    return num;
}
