Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,58 @@ Otherwise, it is set to **black** (`R = G = B = 0`).
This results in a high-contrast, two-tone image where all intermediate shades are eliminated — essentially a hard binary “black-and-white” conversion.


### 7.) The Edge Detection (Sobel) Algorithm

The “edge detection” filter highlights sharp changes in pixel intensity, producing a sketch-like outline of the image.

For each pixel, the horizontal and vertical gradients are calculated using a 3×3 Sobel kernel applied to the surrounding pixels:

Horizontal (Gx):
-1 0 1
-2 0 2
-1 0 1

Vertical (Gy):
-1 -2 -1
0 0 0
1 2 1

The gradient magnitude for each color channel is then computed as:

value
=
𝐺
𝑥
2
+
𝐺
𝑦
2
value=
Gx
2
+Gy
2


The result is clamped between 0 and 255 and replaces the original pixel value. This produces a monochrome image where edges are highlighted, giving a pencil-sketch effect.



### Pixelate Filter

The “Pixelate” filter divides the image into small square blocks (default 5x5) and replaces each block with the average color of its pixels. This creates a mosaic-like effect, useful for artistic rendering or obscuring parts of an image for privacy.

Algorithm Steps:

1. Divide the image into blocks of size blockSize x blockSize.
2. For each block:
a. Compute the average Red, Green, and Blue values of all pixels in the block.
b. Replace all pixels in the block with the computed average color.
3. Repeat until all blocks are processed.


---

### Usage
Expand Down
49 changes: 28 additions & 21 deletions filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,24 @@
int main(int argc, char *argv[])
{
// Define allowable filters
char *filters = "bgrsivt";
char *filters = "bgrsivtp";




char filterArr[argc-3];

// gets all filter flags and checks validity
for(int i=0; i<argc; i++){
char temp = getopt(argc,argv,filters);
if(temp == -1) break;
filterArr[i]= temp;
if(filterArr[i] == '?') {
printf("Invalid filter option");
return 1;
}
}
for(int i=0; i<argc; i++){
char temp = getopt(argc,argv,filters);
if(temp == -1) break;
filterArr[i]= temp;
if(filterArr[i] == '?') {
printf("Invalid filter option");
return 1;
}
}


// Ensure proper usage
if (argc < optind + 2)
{
printf("Usage: ./filter [flag] infile outfile\n");
return 3;
}


// Remember filenames
char *infile = argv[optind];
Expand Down Expand Up @@ -131,10 +126,22 @@ int main(int argc, char *argv[])
case 't':
threshold(height, width, image);
break;
default:
printf("%c", &filterArr[i]);





case 'p':
apply_pixelate(height, width, image, 5);
break;


default:
printf("Unknown filter: %c\n", filterArr[i]);
free(image);
fclose(inptr);
fclose(outptr);
return 7;

}
}
// Write outfile's BITMAPFILEHEADER
Expand Down
Binary file added filter.exe
Binary file not shown.
57 changes: 57 additions & 0 deletions helpers.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "helpers.h"
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include "bmp.h"
int min(int a,int b){
if(a<b) return a;
Expand Down Expand Up @@ -198,3 +200,58 @@ void threshold(int height, int width, RGBTRIPLE image[height][width])
}
}
}



// Pixelate filter — separate function, not nested
void apply_pixelate(int height, int width, RGBTRIPLE image[height][width], int blockSize)
{

RGBTRIPLE **copy = malloc(height * sizeof(RGBTRIPLE *));
for (int i = 0; i < height; i++)
copy[i] = malloc(width * sizeof(RGBTRIPLE));

for (int i = 0; i < height; i += blockSize)
{
for (int j = 0; j < width; j += blockSize)
{
int sumRed = 0, sumGreen = 0, sumBlue = 0;
int count = 0;

for (int bi = 0; bi < blockSize && (i + bi) < height; bi++)
{
for (int bj = 0; bj < blockSize && (j + bj) < width; bj++)
{
sumRed += image[i + bi][j + bj].rgbtRed;
sumGreen += image[i + bi][j + bj].rgbtGreen;
sumBlue += image[i + bi][j + bj].rgbtBlue;
count++;
}
}

unsigned char avgRed = sumRed / count;
unsigned char avgGreen = sumGreen / count;
unsigned char avgBlue = sumBlue / count;

for (int bi = 0; bi < blockSize && (i + bi) < height; bi++)
{
for (int bj = 0; bj < blockSize && (j + bj) < width; bj++)
{
image[i + bi][j + bj].rgbtRed = avgRed;
image[i + bi][j + bj].rgbtGreen = avgGreen;
image[i + bi][j + bj].rgbtBlue = avgBlue;
}
}
}


}


for (int i = 0; i < height; i++)
free(copy[i]);
free(copy);
}

// Free temporary array

13 changes: 13 additions & 0 deletions helpers.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#ifndef HELPERS_H
#define HELPERS_H

#include <stdio.h>
#include <math.h>

#include "bmp.h"

// Convert image to grayscale
Expand All @@ -19,3 +25,10 @@ void vignette(int height, int width, RGBTRIPLE image[height][width]);

//Threshold Filter(Black & White)
void threshold(int height, int width, RGBTRIPLE image[height][width]);


// Pixelate filter
void apply_pixelate(int height, int width, RGBTRIPLE image[height][width], int blockSize);


#endif
Binary file added output.bmp
Binary file not shown.