[TASK] Begin implementing filters with overflow modes.
This commit is contained in:
parent
6c137b1c6a
commit
57923519df
|
@ -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.
|
||||
|
|
|
@ -158,6 +158,7 @@ class ImageViewer : public QMainWindow {
|
|||
void succeedingHistogrammAdaption();
|
||||
void changeFilterSize(int s);
|
||||
void applyBasicFilter();
|
||||
void applyBasicFilterWithOverflowHandling();
|
||||
|
||||
void open();
|
||||
void openReference();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue