c++c++11bitmapqt5image-editing

Changing <QBitmap> / <QImage>'s contrast


I've used an example code (source: https://forum.qt.io/topic/11390/increasing-contrast-of-qimage/4) to change contrast of a QImage (I've also edited it a little) :

    void SetBetween0and255(double& value)
    {
        if(value > 255)
            value = 255;
        if(value < 0)
            value = 0;
    }
    void CreateHistogram(QMap<QRgb,long>& histo, QImage& image)
    {
        QRgb c = 0;
        int l, k;
        histo.clear();
        for(k = 0; k < image.width(); ++k)
            for( l = 0; l < image.height(); ++l) {
                c = image.pixel(k,l);
                if(!histo.contains(c))
                    histo.insert(c,0);
            }
        //computation of occurences
        for( k = 0; k < image.width(); ++k)
            for( l = 0; l < image.height(); ++l) {
                c = image.pixel(k,l);
                histo[c] = histo[c]+1;
            }
    }
    
    void ImageViewer::ChangeContrast()
    {
        newImage = image.copy();
        QMap<QRgb,long> histo; // histogram map
        CreateHistogram(histo, newImage);
        //compute average value
        long sum_1 = 0, sum_2 = 0;
        QMap<QRgb,long>::iterator j;
        for(j = histo.begin();j!=histo.end();j++) {
            sum_1+=j.value()*j.key();
        }
        for(j = histo.begin();j!=histo.end();j++) {
            sum_2+=j.value();
        }
        long av = sum_1/sum_2;
        //changing contrast of an newImage by factor getted from horizontal slider ui:
        double factor = (double)( (double)sliderBar->value() )/100 ;    // to change also
    
        QRgb c = 0;
        int l, k, r = qRed(av), g = qGreen(av), b = qBlue(av);
        if(factor!=1)
        for (l = 0; l < newImage.height(); ++l) {
            for (k = 0; k < newImage.width(); ++k) {
                c = QRgb(newImage.pixel(k,l));
                QColor col(c);
                col.getRgb(&r,&g,&b);
                double r_n = r / 255.0;
                r_n -= 0.5; r_n *= factor;
                r_n += 0.5; r_n *= 255;
                double g_n = g / 255.0;
                g_n -= 0.5; g_n *= factor;
                g_n += 0.5; g_n *= 255;
                double b_n = b / 255.0;
                b_n -= 0.5; b_n *= factor;
                b_n += 0.5; b_n *= 255;
                SetBetween0and255(r_n);
                SetBetween0and255(g_n);
                SetBetween0and255(b_n);
                newImage.setPixel(k,l,qRgb((int)r_n,(int)g_n,(int)b_n));
            }
        }
        setImage(newImage);
    }

But it feels like there is something wrong with the below lines of code :

        r_n -= 0.5; r_n *= factor;
        r_n += 0.5; r_n *= 255;
        double g_n = g / 255.0;
        g_n -= 0.5; g_n *= factor;
        g_n += 0.5; g_n *= 255;
        double b_n = b / 255.0;
        b_n -= 0.5; b_n *= factor;
        b_n += 0.5; b_n *= 255;

Is there something I can also correct here to change the actual contrast of an image? Because right now what's happening is that the resulting image (newImage) only changes its colour to more "grey" and it becomes 100% grey when "factor" increases its value. The more the "factor" variable, the more the image's "greyness", It doesn't look like I'm actually changing the contrast.

The result


Solution

  • I just had to set the factor variable from ~1 to ~30 to change the contrast by giving these values to the function and the QSlider returned incorrect values.

    It is also possible to reverse the image colors by passing values from -1 to -30, to also change the contrast of the reversed image.

    so the right code will be like:

    // creating QSpinBox instead of QSlider and doing stuff 
    //...
    QSpinBox *qSpinBox = new QSpinBox(this);
    int height = 100, int width = 10;
    QSpinBox->move(width, height); ( move it manually somewhere to see the spinbox widget clear ) 
    //...
    //from 1 to 30 || from -1 to -30
    double factor = (double)( (double)qSpinBox->value() )/100 ;