Skip to content
Merged
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
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,43 @@ 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.

---

### Usage
Expand Down
17 changes: 14 additions & 3 deletions filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
int main(int argc, char *argv[])
{
// Define allowable filters
char *filters = "bgrsivB:";
char *filters = "bgrsivtdB:";


char filterArr[argc-3];
Expand Down Expand Up @@ -130,6 +130,14 @@ int main(int argc, char *argv[])
vignette(height, width, image);
break;

case 't':
threshold(height, width, image);
break;

case 'd': // Edge Detection
detect_edges(height, width, image);
break;

// Brightness Adjust
case 'B': {
int brightness_value = atoi(optarg);
Expand All @@ -138,7 +146,10 @@ int main(int argc, char *argv[])
}
default:
printf("Unknown filter: %c\n", filterArr[i]);
break;
free(image);
fclose(inptr);
fclose(outptr);
return 7;

}
}
Expand Down Expand Up @@ -168,4 +179,4 @@ int main(int argc, char *argv[])
fclose(inptr);
fclose(outptr);
return 0;
}
}
Binary file added filter.exe
Binary file not shown.
70 changes: 70 additions & 0 deletions helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,73 @@ void threshold(int height, int width, RGBTRIPLE image[height][width])
}
}
}
void detect_edges(int height, int width, RGBTRIPLE image[height][width])
{
// Temporary copy of the image
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++)
for (int j = 0; j < width; j++)
copy[i][j] = image[i][j];

// Sobel kernels
int Gx[3][3] = {
{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1}
};
int Gy[3][3] = {
{-1, -2, -1},
{ 0, 0, 0},
{ 1, 2, 1}
};

for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int sumRx = 0, sumGx = 0, sumBx = 0;
int sumRy = 0, sumGy = 0, sumBy = 0;

for (int di = -1; di <= 1; di++)
{
for (int dj = -1; dj <= 1; dj++)
{
int ni = i + di;
int nj = j + dj;

if (ni >= 0 && ni < height && nj >= 0 && nj < width)
{
RGBTRIPLE pixel = copy[ni][nj];
int kx = Gx[di + 1][dj + 1];
int ky = Gy[di + 1][dj + 1];

sumRx += pixel.rgbtRed * kx;
sumGx += pixel.rgbtGreen * kx;
sumBx += pixel.rgbtBlue * kx;

sumRy += pixel.rgbtRed * ky;
sumGy += pixel.rgbtGreen * ky;
sumBy += pixel.rgbtBlue * ky;
}
}
}

// Calculate gradient magnitude and clamp
int red = min(max((int)round(sqrt(sumRx*sumRx + sumRy*sumRy)), 0), 255);
int green = min(max((int)round(sqrt(sumGx*sumGx + sumGy*sumGy)), 0), 255);
int blue = min(max((int)round(sqrt(sumBx*sumBx + sumBy*sumBy)), 0), 255);

image[i][j].rgbtRed = red;
image[i][j].rgbtGreen = green;
image[i][j].rgbtBlue = blue;
}
}

// Free temporary array
for (int i = 0; i < height; i++)
free(copy[i]);
free(copy);
}
15 changes: 15 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 @@ -15,8 +21,17 @@ void reflect(int height, int width, RGBTRIPLE image[height][width]);
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width]);

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

// *New: Edge Detection filter*
void detect_edges(int height, int width, RGBTRIPLE image[height][width]);

// Brightness adjustment filter
void brightness(int height, int width, RGBTRIPLE image[height][width], int value);

// Vignette filter
void vignette(int height, int width, RGBTRIPLE image[height][width]);


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