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
- "Contrast in wiki":http://en.wikipedia.org/wiki/Contrast_(vision)
- "Histogram egalization":http://en.wikipedia.org/wiki/Histogram_equalization#Histogram_equalization_of_color_images