#define filterWidth 3
#define filterHeight 3
double filter[filterHeight][filterWidth] =
{
0, 0, 0,
0, 1, 0,
0, 0, 0
};
double factor = 1.0;
double bias = 0.0;
int main(int argc, char *argv[])
{
//load the image into the buffer
unsigned long w = 0, h = 0;
std::vector<ColorRGB> image;
loadImage(image, w, h, "pics/photo3.png");
std::vector<ColorRGB> result(image.size());
//set up the screen
screen(w, h, 0, "Filters");
ColorRGB color; //the color for the pixels
//apply the filter
for(int x = 0; x < w; x++)
for(int y = 0; y < h; y++)
{
double red = 0.0, green = 0.0, blue = 0.0;
//multiply every value of the filter with corresponding image pixel
for(int filterY = 0; filterY < filterHeight; filterY++)
for(int filterX = 0; filterX < filterWidth; filterX++)
{
int imageX = (x  filterWidth / 2 + filterX + w) % w;
int imageY = (y  filterHeight / 2 + filterY + h) % h;
red += image[imageY * w + imageX].r * filter[filterY][filterX];
green += image[imageY * w + imageX].g * filter[filterY][filterX];
blue += image[imageY * w + imageX].b * filter[filterY][filterX];
}
//truncate values smaller than zero and larger than 255
result[y * w + x].r = min(max(int(factor * red + bias), 0), 255);
result[y * w + x].g = min(max(int(factor * green + bias), 0), 255);
result[y * w + x].b = min(max(int(factor * blue + bias), 0), 255);
}
//draw the result buffer to the screen
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
pset(x, y, result[y * w + x]);
}
//redraw & sleep
redraw();
sleep();
}

//take absolute value and truncate to 255
result[y * w + x].r = min(abs(int(factor * red + bias)), 255);
result[y * w + x].g = min(abs(int(factor * green + bias)), 255);
result[y * w + x].b = min(abs(int(factor * blue + bias)), 255);

#define filterWidth 3
#define filterHeight 3
double filter[filterHeight][filterWidth] =
{
0.0, 0.2, 0.0,
0.2, 0.2, 0.2,
0.0, 0.2, 0.0
};
double factor = 1.0;
double bias = 0.0;

#define filterWidth 5
#define filterHeight 5
double filter[filterHeight][filterWidth] =
{
0, 0, 1, 0, 0,
0, 1, 1, 1, 0,
1, 1, 1, 1, 1,
0, 1, 1, 1, 0,
0, 0, 1, 0, 0,
};
double factor = 1.0 / 13.0;
double bias = 0.0;

#define filterWidth 9
#define filterHeight 9
double filter[filterHeight][filterWidth] =
{
1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1,
};
double factor = 1.0 / 9.0;
double bias = 0.0;

#define filterWidth 5
#define filterHeight 5
double filter[filterHeight][filterWidth] =
{
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 2, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
};
double factor = 1.0;
double bias = 0.0;

#define filterWidth 5
#define filterHeight 5
double filter[filterHeight][filterWidth] =
{
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 4, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
};
double factor = 1.0;
double bias = 0.0;

#define filterWidth 5
#define filterHeight 5
double filter[filterHeight][filterWidth] =
{
1, 0, 0, 0, 0,
0, 2, 0, 0, 0,
0, 0, 6, 0, 0,
0, 0, 0, 2, 0,
0, 0, 0, 0, 1,
};
double factor = 1.0;
double bias = 0.0;

#define filterWidth 3
#define filterHeight 3
double filter[filterHeight][filterWidth] =
{
1, 1, 1,
1, 8, 1,
1, 1, 1
};
double factor = 1.0;
double bias = 0.0;

#define filterWidth 3
#define filterHeight 3
double filter[filterHeight][filterWidth] =
{
1, 1, 1,
1, 9, 1,
1, 1, 1
};
double factor = 1.0;
double bias = 0.0;

#define filterWidth 5
#define filterHeight 5
double filter[filterHeight][filterWidth] =
{
1, 1, 1, 1, 1,
1, 2, 2, 2, 1,
1, 2, 8, 2, 1,
1, 2, 2, 2, 1,
1, 1, 1, 1, 1,
};
double factor = 1.0 / 8.0;
double bias = 0.0;

#define filterWidth 3
#define filterHeight 3
double filter[filterHeight][filterWidth] =
{
1, 1, 1,
1, 7, 1,
1, 1, 1
};
double factor = 1.0;
double bias = 0.0;

#define filterWidth 3
#define filterHeight 3
double filter[filterHeight][filterWidth] =
{
1, 1, 0,
1, 0, 1,
0, 1, 1
};
double factor = 1.0;
double bias = 128.0;

#define filterWidth 5
#define filterHeight 5
double filter[filterHeight][filterWidth] =
{
1, 1, 1, 1, 0,
1, 1, 1, 0, 1,
1, 1, 0, 1, 1,
1, 0, 1, 1, 1,
0, 1, 1, 1, 1
};
double factor = 1.0;
double bias = 128.0;

#define filterWidth 3
#define filterHeight 3
double filter[filterHeight][filterWidth] =
{
1, 1, 1,
1, 1, 1,
1, 1, 1
};
double factor = 1.0 / 9.0;
double bias = 0.0;

#define filterWidth 3
#define filterHeight 3
//color arrays
int red[filterWidth * filterHeight];
int green[filterWidth * filterHeight];
int blue[filterWidth * filterHeight];
int selectKth(int* data, int s, int e, int k);
int main(int argc, char *argv[])
{
//load the image into the buffer
unsigned long w = 0, h = 0;
std::vector<ColorRGB> image;
loadImage(image, w, h, "pics/noise.png");
std::vector<ColorRGB> result(image.size());
//set up the screen
screen(w, h, 0, "Median Filter");
ColorRGB color; //the color for the pixels
//apply the filter
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
int n = 0;
//set the color values in the arrays
for(int filterY = 0; filterY < filterHeight; filterY++)
for(int filterX = 0; filterX < filterWidth; filterX++)
{
int imageX = (x  filterWidth / 2 + filterX + w) % w;
int imageY = (y  filterHeight / 2 + filterY + h) % h;
red[n] = image[imageY * w + imageX].r;
green[n] = image[imageY * w + imageX].g;
blue[n] = image[imageY * w + imageX].b;
n++;
}
int filterSize = filterWidth * filterHeight;
result[y * w + x].r = red[selectKth(red, 0, filterSize, filterSize / 2)];
result[y * w + x].g = green[selectKth(green, 0, filterSize, filterSize / 2)];
result[y * w + x].b = blue[selectKth(blue, 0, filterSize, filterSize / 2)];
}
//draw the result buffer to the screen
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
pset(x, y, result[y * w + x]);
}
//redraw & sleep
redraw();
sleep();
}

// selects the kth largest element from the data between start and end (end exclusive)
int selectKth(int* data, int s, int e, int k)
{
// 5 or less elements: do a small insertion sort
if(e  s <= 5)
{
for(int i = s + 1; i < e; i++)
for(int j = i; j > 0 && data[j  1] > data[j]; j) std::swap(data[j], data[j  1]);
return s + k;
}
int p = (s + e) / 2; // choose simply center element as pivot
// partition around pivot into smaller and larger elements
std::swap(data[p], data[e  1]); // temporarily move pivot to the end
int j = s; // new pivot location to be calculated
for(int i = s; i + 1 < e; i++)
if(data[i] < data[e  1]) std::swap(data[i], data[j++]);
std::swap(data[j], data[e  1]);
// recurse into the applicable partition
if(k == j  s) return s + k;
else if(k < j  s) return selectKth(data, s, j, k);
else return selectKth(data, j + 1, e, k  j + s  1); // subtract amount of smaller elements from k
}
