#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace std;
using namespace cv;

/**
 * @brief Compute and draw the histogram of B, G, R channels of an image.
 * 
 * Reads an image from file, calculates per-channel histograms,
 * normalizes them, and draws them on a canvas. 
 * Finally, saves the result as an image file.
 * 
 * @return int Exit code: 0 if success, -1 if image not found.
 */
int cal_hist()
{
    Mat src = imread("./a.jpg");
    if (src.empty()) 
    {
        cout << "Image not found" << endl;
        return -1;
    }

    vector<Mat> all_channel;
    split(src, all_channel);

    const int bin = 256;
    float bin_range[2] = { 0, 255 };
    const float* ranges[1] = { bin_range };

    Mat b_hist, g_hist, r_hist;
    calcHist(&all_channel[0], 1, 0, Mat(), b_hist, 1, &bin, ranges, true, false);
    calcHist(&all_channel[1], 1, 0, Mat(), g_hist, 1, &bin, ranges, true, false);
    calcHist(&all_channel[2], 1, 0, Mat(), r_hist, 1, &bin, ranges, true, false);

    int hist_w = 512;
    int hist_h = 400;
    int bin_w = cvRound((double)hist_w / bin);
    Mat hist_canvas = Mat::zeros(hist_h, hist_w, CV_8UC3);

    normalize(b_hist, b_hist, 0, 255, NORM_MINMAX, -1, Mat());
    normalize(g_hist, g_hist, 0, 255, NORM_MINMAX, -1, Mat());
    normalize(r_hist, r_hist, 0, 255, NORM_MINMAX, -1, Mat());

    for (int i = 1; i < bin; i++)
    {
        line(hist_canvas,
             Point((i - 1) * bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))),
             Point(i * bin_w, hist_h - cvRound(b_hist.at<float>(i))),
             Scalar(255, 0, 0), 2);
        line(hist_canvas,
             Point((i - 1) * bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))),
             Point(i * bin_w, hist_h - cvRound(g_hist.at<float>(i))),
             Scalar(0, 255, 0), 2);
        line(hist_canvas,
             Point((i - 1) * bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))),
             Point(i * bin_w, hist_h - cvRound(r_hist.at<float>(i))),
             Scalar(0, 0, 255), 2);
    }

    imwrite("lena_hist.jpg", hist_canvas);
    return 0;
}

void setup() {
  // put your setup code here, to run once:
  cal_hist();
}

void loop() {
  // put your main code here, to run repeatedly:

}
