CG2_Tasks/lazy_image.cpp

201 lines
5.7 KiB
C++

#ifndef LAZY_IMAGE_C
#define LAZY_IMAGE_C
#include <QtGlobal>
#include <QMainWindow>
#include <QColor>
#include <iostream>
#include <math.h>
class LazyImage {
private:
QImage* img; //Not managed by us, just used.
QImage* histogramm_normal_image;
QImage* histogramm_cumulative_image;
double histogramm_relative_intensity[256];
int histogramm_absolute_intensity[256];
int histogramm_absolute_cumulative_intensity[256];
int intensity_average;
int intensity_variance;
void gatherHistogrammData(void) {
// Zero existing histogramm data first
for(int i=0; i<256; i++) {
histogramm_relative_intensity[i] = 0;
histogramm_absolute_intensity[i] = 0;
histogramm_absolute_cumulative_intensity[i] = 0;
}
// Count all the brightness values
for(int x=0; x<this->img->width(); x++) {
for(int y=0; y<this->img->height(); y++) {
int r,g,b;
QColor color = QColor::fromRgb(this->img->pixel(x, y));
color.getRgb(&r,&g,&b);
int intensity = this->calcIntensity(r, g, b);
histogramm_absolute_intensity[intensity] += 1;
}
}
// Calculate relative histogramm and absolute cumulative histogramm
int pixels = this->img->width()*this->img->height();
int sum = 0;
for(int i=0; i<256; i++) {
histogramm_relative_intensity[i] = (((double) histogramm_absolute_intensity[i])/((double) pixels));
sum += histogramm_absolute_intensity[i];
histogramm_absolute_cumulative_intensity[i] = sum;
}
};
void calcIntensityAverage(void) {
double sum = 0;
for(int i=0; i<256;i++) {
sum += (i*histogramm_relative_intensity[i]);
}
this->intensity_average = (int) qRound(sum);
};
void calcIntensityVariance(void) {
int intensity_average = this->intensity_average;
int sum_difference = 0;
for(int x=0; x<this->img->width(); x++) {
for(int y=0; y<this->img->height(); y++) {
QColor color = QColor::fromRgb(this->img->pixel(x, y));
int r,g,b;
color.getRgb(&r,&g,&b);
sum_difference += std::abs(this->calcIntensity(r, g, b) - intensity_average);;
}
}
this->intensity_variance = (int) qRound(sum_difference/(this->img->width()*this->img->height()));
};
void generateNormalHistogrammImage(void) {
if(this->histogramm_normal_image != NULL) {
delete this->histogramm_normal_image;
this->histogramm_normal_image = NULL;
}
//Find biggest value in histogramm data
double max = 0;
for(int i=0; i<256; i++) {
if(histogramm_relative_intensity[i] > max) max = histogramm_relative_intensity[i];
}
this->histogramm_normal_image = new QImage(256, 100, QImage::Format_RGB32);
this->histogramm_normal_image->fill(QColor::fromRgb(200,200,200));
int black = QColor::fromRgb(0,0,0).rgb();
for(int x=0; x<256; x++) {
int k_max = (int) qRound((100*histogramm_relative_intensity[x])/max);
for(int y=0; y<k_max; y++) {
this->histogramm_normal_image->setPixel(x, (100-y)-1, black);
}
}
};
void generateCumulativeHistogrammImage(void) {
if(this->histogramm_cumulative_image != NULL) {
delete this->histogramm_cumulative_image;
this->histogramm_cumulative_image = NULL;
}
this->histogramm_cumulative_image = new QImage(256, 100, QImage::Format_RGB32);
this->histogramm_cumulative_image->fill(QColor::fromRgb(200,200,200));
int black = QColor::fromRgb(0,0,0).rgb();
double total = 0.0;
for(int x=0; x<256; x++) {
total += histogramm_relative_intensity[x];
int k_max = (int) qRound(100*total);
for(int y=0; y<k_max; y++) {
this->histogramm_cumulative_image->setPixel(x, (100-y)-1, black);
}
}
};
public:
LazyImage(QImage* img) {
this->histogramm_normal_image = NULL;
this->histogramm_cumulative_image = NULL;
this->setImage(img);
};
~LazyImage() {
if(img != NULL) {
img = NULL;
}
};
void setImage(QImage* img) {
if(img != NULL) {
this->img = img;
this->updateStatistics();
}
};
QImage* getImage(void) {
return this->img;
};
void updateStatistics(void) {
this->gatherHistogrammData();
this->calcIntensityAverage();
this->calcIntensityVariance();
this->generateNormalHistogrammImage();
this->generateCumulativeHistogrammImage();
};
QImage* getHistogrammNormalImage(void) {
return this->histogramm_normal_image;
};
QImage* getHistogrammCumulativeImage(void) {
return this->histogramm_cumulative_image;
};
/**
* Uses simple weights to calculate intensity of a pixel.
* Using qRound() to reduce the error of the int cast.
*
* @brief LazyImage::calcIntensity
*/
int calcIntensity(int r, int g, int b) {
return (int) qRound(0.299*r + 0.587*g + 0.114*b);
};
int getIntensityAverage(void) {
return this->intensity_average;
}
int getIntensityVariance(void) {
return this->intensity_variance;
};
int* getAbsoluteIntensityHistogramm(void) {
return this->histogramm_absolute_intensity;
};
int* getAbsoluteCumulativeIntensityHistogramm(void) {
return this->histogramm_absolute_cumulative_intensity;
};
double* getRelativeIntensityHistogramm(void) {
return this->histogramm_relative_intensity;
};
void convertToMonochrome(void) {
for(int x=0; x<this->img->width(); x++) {
for(int y=0; y<this->img->height(); y++) {
int r,g,b;
QColor color = QColor::fromRgb(this->img->pixel(x, y));
color.getRgb(&r,&g,&b);
int intensity = this->calcIntensity(r, g, b);
color = QColor::fromRgb(intensity, intensity, intensity);
this->img->setPixel(x, y, color.rgb());
}
}
};
};
#endif