RGB Histogram with QBarSeries

1.4k views Asked by At

I followd this Example to draw a RGB-Histogram with Qt. I have three different QBarSets, one for each color channel.

My problem now is that all the bars are drawn next to each other. Is it somehow possible to draw the bars in front of each other?


That's how it looks right now: enter image description here

And that's how I would like it: Link

Since the bars are all drawn next to each other in my example, they are much too narrow.

1

There are 1 answers

0
Käseknacker On BEST ANSWER

I solved my problem with a QStackedBarSeries and a few calculations by hand.

My Code:

// Histogramms
std::vector<int> nGrayValues(NOGRAYLEVELS, 0);
std::vector<int> nRedValues(NOGRAYLEVELS, 0);
std::vector<int> nGreenValues(NOGRAYLEVELS, 0);
std::vector<int> nBlueValues(NOGRAYLEVELS, 0);

QRgb* imPixels= reinterpret_cast< QRgb* >(image.bits());
for (quint64 i = 0; i < numberPixels; i++) {
    nGrayValues[static_cast<unsigned int>(qGray(imPixels[i]))]++;
    nRedValues[static_cast<unsigned int>(qRed(imPixels[i]))]++;
    nGreenValues[static_cast<unsigned int>(qGreen(imPixels[i]))]++;
    nBlueValues[static_cast<unsigned int>(qBlue(imPixels[i]))]++;
}

QStackedBarSeries* pSeries = new QStackedBarSeries();

QBarSet* grayBarSet = new QBarSet("Gray");
grayBarSet->setColor(Qt::black);
QBarSet* redBarSet = new QBarSet("Red");
redBarSet->setColor(Qt::red);
QBarSet* greenBarSet = new QBarSet("Green");
greenBarSet->setColor(Qt::green);
QBarSet* blueBarSet = new QBarSet("Blue");
blueBarSet->setColor(Qt::blue);

double totalMaxValue = 0.0;
if (numberPixels != 0) {
    double numberPixels_f = static_cast<double>(numberPixels);
    for (unsigned int i = 0; i < NOGRAYLEVELS; i++) {

        // Helper function
        auto calcPart = [=](int value, int& maxValue) -> int 
                        {
                            int temp = value - maxValue;
                            if (temp > 0) {
                                maxValue = value;
                                return temp;
                            } else {
                                return 0;
                            }
                         };

        int grayPart = 0, redPart = 0, greenPart = 0, bluePart = 0, maxPart = 0;
        grayPart = calcPart(nGrayValues[i], maxPart);
        redPart = calcPart(nRedValues[i], maxPart);
        greenPart = calcPart(nGreenValues[i], maxPart);
        bluePart = calcPart(nBlueValues[i], maxPart);

        // normalize histogramm entries as procent
        *grayBarSet << grayPart * 100.0 / numberPixels_f;
        *redBarSet << redPart * 100.0 / numberPixels_f;
        *greenBarSet << greenPart * 100.0 / numberPixels_f;
        *blueBarSet << bluePart * 100.0 / numberPixels_f;

        double m1 = std::max(gray, red);
        double m2 = std::max(green, blue);
        double maxValue = std::max(m1, m2);
        if (maxValue > totalMaxValue) {
            totalMaxValue = maxValue;
        }
    }
}

pSeries->append(grayBarSet);
pSeries->append(redBarSet);
pSeries->append(greenBarSet);
pSeries->append(blueBarSet);

// add series to the chart and update axisY
pChart->removeAllSeries();
axisY->setRange(0, totalMaxValue);
pChart->addSeries(pSeries);

The individual colors are drawn in a fixed sequence (gray -> red -> green -> blue).


This is the result: Stacked Histogram