Increasing contrast of QImage



  • Hello,

    I develop GUI and algorithm for editing images , ideally it should work like Photoshop ( hhh ).
    I've already made brightness control algorithm and UI and now I'm working on contrast increase/decrease of QImage,

    next code ( part of a class method ) computes histogram of QImage ( imageToProcess and prev_image are class variables ), finds histogram center ( middle ) and tries to change image contrast by input value factor ( from 0 to 1 ) :

    @
    QMap<QRgb,long> histo; // histogram map
    QMap<QRgb,long>::iterator j;
    QRgb c = 0;
    int l, k;
    histo.clear();
    for(k = 0; k < prev_image.width(); ++k)
    for( l = 0; l < prev_image.height(); ++l) {
    c = prev_image.pixel(k,l);

            if(!histo.contains(c))
                histo.insert(c,0);
        }
     //computation of occurences
     for( k = 0; k < prev_image.width(); ++k)
        for( l = 0; l < prev_image.height(); ++l) {
            c = prev_image.pixel(k,l);
            histo[c] = histo[c]+1;
        }
                 //compute average value
                 long sum_1 = 0;
                 long sum_2 = 0;
                 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;
                 av_r = qRed(av);
                 av_g = qGreen(av);
                 av_b = qBlue(av);
                //changing contrast of an image by factor getted from horizontal slider ui:
                double factor = (double)( (double)ie->horizontalSlider_2->value() )/100 ;    // to change also  
                if(factor!=0.99)
                for (int y = 0; y < prev_image.height(); ++y) {
                for (int x = 0; x < prev_image.width(); ++x) {
                c = QRgb(prev_image.pixel(x,y));
                QColor col(c);
                col.getRgb(&r,&g,&b);
                r = (int)(r*(1-factor)+av_r*factor);
                g = (int)(g*(1-factor)+av_g*factor);
                b = (int)(b*(1-factor)+av_b*factor);
                if(r>255)
                    r=255;
                if(g>255)
                    g=255;
                if(b>255)
                    b=255;
                imageToProcess->setPixel(x,y,qRgb(r,g,b));
             }
          }
            if(factor!=0.99)
                    this->ie->label_11->setPixmap(QPixmap::fromImage(imageToProcess->scaled(this->ie->label_11->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation)));
            else
                    this->ie->label_11->setPixmap(QPixmap::fromImage(prev_image.scaled(this->ie->label_11->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation)));@
    

    But actually what happens is that a contrast of an image changes ( only decreases in such a way ) and a background gets green when initial background is black or red when initial background is white.

    How to increase contrast also ?

    What to fix so that a background stays the same after contrast changing manipulations and does not get green/red ?

    Sorry if the code is not formatted / eased to read.

    Thanks in advance.



  • Well it's not really suprising as you in a certain point you multiply QRgb with long, assign the result to long and then tryto get color components of that. I don't if the algorithm is correct in general, but you absolutely should keep color channels independent.



  • A small remark:
    @
    c = QRgb(prev_image.pixel(x,y));
    QColor col(c);
    col.getRgb(&r,&g,&b);
    r = (int)(r*(1-factor)+av_rfactor);
    g = (int)(g
    (1-factor)+av_gfactor);
    b = (int)(b
    (1-factor)+av_b*factor);
    @

    why not simplify and don't use QColor:

    @
    c = prev_image.pixel(x,y);

           int r = (int)(c.red()*(1-factor)+av_r*factor);
           int g = (int)(c.green()*(1-factor)+av_g*factor);
           int b = (int)(c.blue()*(1-factor)+av_b*factor);
    

    @

    Now the problem is really your algorithm:

    the average you calculate is like a random value: when you cumulate color values you should take of the overflow (ex with 10 pixels: 2x grey and 8x white: (20x808080 + 80xFFFFFF) / 10 = 0x90100F I use only grey and white and now I get a very strange color/factor?? )

    it's not possible to decompose your 'average' in RGB component values like you: because a grey could have after transformation any color: 128cst1 + av_rcst2 != 128cst1 + av_gcst2 -> no more grey.



  • Hello, thanks for you answers.
    I've came up with another algorithm like next :
    @ if(factor!=1)
    for (l = 0; l < working_image.height(); ++l) {
    for (k = 0; k < working_image.width(); ++k) {
    c = QRgb(working_image.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;
    if(r_n>255)
    r_n=255;
    if(r_n<0)
    r_n=0;
    if(g_n>255)
    g_n=255;
    if(g_n<0)
    g_n=0;
    if(b_n>255)
    b=255;
    if(b_n<0)
    b_n=0;
    imageToProcess->setPixel(k,l,qRgb((int)r_n,(int)g_n,(int)b_n));
    }
    }@

    That works better but still far from perfect. I can't understand yet a better approach.



  • Contrast in general is not a very simple thing, please check here


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.