[TASK] Begin implementing filters with overflow modes.

This commit is contained in:
Jan Philipp Timme 2015-12-04 12:57:31 +01:00
parent 6c137b1c6a
commit 57923519df
3 changed files with 116 additions and 1 deletions

View File

@ -537,7 +537,69 @@ void ImageViewer::applyBasicFilter() {
updateImageDisplay();
}
/**
* Basic filter PLUS different overflow modes
*
* @brief ImageViewer::applyBasicFilterWithOverflowHandling
*/
void ImageViewer::applyBasicFilterWithOverflowHandling() {
// TODO: Get overflow mode here
LazyImage::overflowMode overflowMode = LazyImage::CONSTANT;
logFile << "Applying basic filter - overflow mode: " << overflowMode << std::endl;
renewLogging();
int* data = filter_gui->getData();
int filter_size = filter_gui->getSize();
// sum up the filter weights
int filter_sum = 0;
for(int i=0; i<filter_size; i++) {
for(int j=0; j<filter_size; j++) {
int current_data = data[i*filter_size + j];
filter_sum += abs(current_data); // support for negativ weights using abs()
logFile << "[" << i << "," << j << "] -> " << current_data << " ";
}
logFile << std::endl;
}
logFile << "Beginning calculation ... " << std::endl;
renewLogging();
int h, s, l;
// for each pixel
for(int x=0; x<working_copy->getImage()->width(); x++) {
for(int y=0; y<working_copy->getImage()->height(); y++) {
int intensity_sum = 0;
// sum up weighted intensity for each matrix entry
for(int fx=0; fx<filter_size; fx++) {
int dx = fx - (filter_size / 2);
for(int fy=0; fy<filter_size; fy++) {
int dy = fy - (filter_size / 2);
QColor color = QColor::fromRgb(original->getPixel(x+dx, y+dy, overflowMode));
color.getHsl(&h, &s, &l);
//std::cout << "[" << fx << "," << fy <<"] " << l << " * " << data[fx*filter_size + fy] << " = ";
intensity_sum += (l * data[fx*filter_size + fy]);
//std::cout << intensity_sum << std::endl;
}
}
QColor color = QColor::fromRgb(original->getImage()->pixel(x, y));
color.getHsl(&h, &s, &l);
//std::cout << "old lightness: " << l << ", filter_sum: " << filter_sum << ", intensity_sum:" << intensity_sum;
// divide by sum of weights
l = qRound((intensity_sum*1.0) / filter_sum);
//optional clamping for exotic stuff like negative values
if(l > 255) l = 255;
if(l < 0) l = 0;
//std::cout << " --> new l: " << l << std::endl;
color.setHsl(h, s, l);
// and set it.
working_copy->getImage()->setPixel(x, y, color.rgb());
}
}
logFile << "done." << std::endl;
renewLogging();
updateImageDisplay();
}
/****************************************************************************************
*
* GUI elements related to the tasks are set up here.

View File

@ -158,6 +158,7 @@ class ImageViewer : public QMainWindow {
void succeedingHistogrammAdaption();
void changeFilterSize(int s);
void applyBasicFilter();
void applyBasicFilterWithOverflowHandling();
void open();
void openReference();

View File

@ -116,6 +116,8 @@ class LazyImage {
public:
enum overflowMode {ZERO_PADDING, CONSTANT, MIRRORED, CONTINUOUS};
LazyImage(QImage* img) {
this->histogramm_normal_image = NULL;
this->histogramm_cumulative_image = NULL;
@ -201,6 +203,56 @@ class LazyImage {
}
}
};
/**
* Takes coordinates and a mode about how to handle overflows.
* Not all modes are 100% bullet proof - it is still possible to
* get unexpected results out of this for very big overflows.
*
* @brief LazyImage::getPixel
*/
QColor getPixel(int x, int y, overflowMode mode) {
int width = this->img->width();
int height = this->img->height();
QRgb result = NULL;
switch(mode) {
case ZERO_PADDING: // Return black for all out of bound requests
if(x < 0 || x >= width || y < 0 || y >= height) {
result = QRgb(qRgb(0, 0, 0);
}
break;
case CONSTANT: // Simply clamp to the border it is stuck on
if(x < 0) x = 0;
else if(x >= width) x = width - 1;
if(y < 0) y = 0;
else if(y >= height) y = height - 1;
break;
case MIRRORED: // Mirror on overflowed axis
if(x < 0) x *= -1;
else if(x >= width) {
int delta = x - (width-1);
x = (width-1) - delta;
}
if(y < 0) y *= -1;
else if(y > (height-1)) {
int delta = y - (height-1);
y = (height-1) - delta;
}
break;
case CONTINUOUS: // simply start over at the other side again
x = x % width;
y = y % height;
break;
default:
std::cout << "HELP, SOMETHING WENT WRONG! I DON'T KNOW THIS MODE!" << std::endl;
break; // BOOM!
}
if(result == NULL) {
return this->img->pixel(x, y);
} else {
return result;
}
};
};