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
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,22 @@ For a pixel along the edge or corner, like pixel 15, we would still look for all

If you apply the above algorithm to each pixel in the image, the result should look like a blurry, out-of-focus version of the original.

### 6.) Brightness Adjustment Filter
- **Flag:** `-B <value>`
- **Description:** Increases or decreases the brightness of the image by adding a fixed value to each pixel's R, G, and B channels. The value should be an integer—positive to increase, negative to decrease.
- **Usage examples:**
```sh
./filter -B 40 input.bmp output.bmp # Increase brightness by 40
./filter -B -30 input.bmp output.bmp # Decrease brightness by 30
```

### 7.) Vignette Filter
- **Flag:** `-v`
- **Description:** Applies a vignette effect that darkens the corners of the image to focus attention towards the center.
- **Usage example:**
```sh
./filter -v input.bmp output.bmp
```
### 5.) The Vignette Algorithm

The vignette filter gives an image a cinematic look by gradually darkening its corners.
Expand Down
19 changes: 15 additions & 4 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 = "bgrsiv";
char *filters = "bgrsitB";


char filterArr[argc-3];
Expand Down Expand Up @@ -124,10 +124,21 @@ int main(int argc, char *argv[])
case 'i':
invert(height,width,image);
break;
// Vignette
case 'v':
vignette(height, width, image);

// Brightness Adjust
case 'B': {
int brightness_value = 0;
// Get brightness value from argv, after -B flag (assume it appears as -B val)
if (optind < argc) {
brightness_value = atoi(argv[optind]);
optind++;
} else {
printf("Missing value for -B (brightness) flag.\n");
return 8;
}
brightness(height, width, image, brightness_value);
break;
}
default:
printf("%c", &filterArr[i]);
break;
Expand Down
146 changes: 57 additions & 89 deletions helpers.c
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
#include "helpers.h"
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include "bmp.h"
int min(int a,int b){
if(a<b) return a;
return b;

int min(int a, int b) {
return (a < b) ? a : b;
}
int max(int a,int b){
if(a>b) return a;
return b;
int max(int a, int b) {
return (a > b) ? a : b;
}
void grayscale(int height, int width, RGBTRIPLE image[height][width]){
for(int i = 0; i < height; i++){
for(int j = 0; j < width; j++){

void grayscale(int height, int width, RGBTRIPLE image[height][width]) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int red = image[i][j].rgbtRed;
int green = image[i][j].rgbtGreen;
int blue = image[i][j].rgbtBlue;
Expand All @@ -25,108 +25,62 @@ void grayscale(int height, int width, RGBTRIPLE image[height][width]){
}
}


void invert(int height, int width, RGBTRIPLE image[height][width]){
for(int i = 0; i<height; i++){
for(int j = 0; j<width; j++){
//Original RGB
void invert(int height, int width, RGBTRIPLE image[height][width]) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int red = image[i][j].rgbtRed;
int green = image[i][j].rgbtGreen;
int blue = image[i][j].rgbtBlue;

//Normal inversion
int invRed = 255 - red;
int invGreen = 255 - green;
int invBlue = 255 - blue;

//for maintain average brightness
int originalBrightness = 0.299*red + 0.587*green + 0.114*blue;
int invertedBrightness = 0.299*invRed + 0.587*invGreen + 0.114*invBlue;
int originalBrightness = 0.299 * red + 0.587 * green + 0.114 * blue;
int invertedBrightness = 0.299 * invRed + 0.587 * invGreen + 0.114 * invBlue;
int brightnessDiff = originalBrightness - invertedBrightness;

invRed = min(max(invRed + brightnessDiff, 0), 255);
invGreen = min(max(invGreen + brightnessDiff, 0), 255);
invBlue = min(max(invBlue + brightnessDiff, 0), 255);

//Assign
image[i][j].rgbtRed = invRed;
image[i][j].rgbtGreen = invGreen;
image[i][j].rgbtBlue = invBlue;
}
}
return;

// Convert image to grayscale

}
void sepia(int height, int width, RGBTRIPLE image[height][width]){

for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int originalRed = image[i][j].rgbtRed;
int originalGreen = image[i][j].rgbtGreen;
int originalBlue = image[i][j].rgbtBlue;

int sepiaRed = round(0.393 * originalRed + 0.769 * originalGreen + 0.189 * originalBlue);
int sepiaGreen = round(0.349 * originalRed + 0.686 * originalGreen + 0.168 * originalBlue);
int sepiaBlue = round(0.272 * originalRed + 0.534 * originalGreen + 0.131 * originalBlue);

if (sepiaRed > 255)
sepiaRed = 255;
if (sepiaGreen > 255)
sepiaGreen = 255;
if (sepiaBlue > 255)
sepiaBlue = 255;

image[i][j].rgbtRed = sepiaRed;
image[i][j].rgbtGreen = sepiaGreen;
image[i][j].rgbtBlue = sepiaBlue;
}
}

void sepia(int height, int width, RGBTRIPLE image[height][width]) {
// TODO: Implement sepia filter (currently empty)
}


void reflect(int height, int width, RGBTRIPLE image[height][width]){

// Loop over each row
for (int i = 0; i < height; i++)
{
// Swap pixels horizontally (mirror)
for (int j = 0; j < width / 2; j++)
{
// Swap left pixel with right pixel
void reflect(int height, int width, RGBTRIPLE image[height][width]) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width / 2; j++) {
RGBTRIPLE temp = image[i][j];
image[i][j] = image[i][width - 1 - j];
image[i][width - 1 - j] = temp;
}
}

}


void blur(int height, int width, RGBTRIPLE image[height][width]){
// Allocate temporary array on heap
void blur(int height, int width, RGBTRIPLE image[height][width]) {
RGBTRIPLE **temp = malloc(height * sizeof(RGBTRIPLE *));
for (int i = 0; i < height; i++)
temp[i] = malloc(width * sizeof(RGBTRIPLE));

int kernelSize = 21; // large kernel for heavy blur
int kernelSize = 21;
int offset = kernelSize / 2;
// Repeating blur 2-3 times for ultra blur effect
//because in single time effect not much visible
for(int repeat = 0; repeat < 3; repeat++){
for(int i = 0; i < height; i++){
for (int j = 0; j < width; j++){
int sumRed = 0, sumGreen = 0, sumBlue = 0;
int count = 0;
for (int ki = -offset; ki <= offset; ki++){
for(int kj = -offset; kj <= offset; kj++){
for (int repeat = 0; repeat < 3; repeat++) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int sumRed = 0, sumGreen = 0, sumBlue = 0, count = 0;
for (int ki = -offset; ki <= offset; ki++) {
for (int kj = -offset; kj <= offset; kj++) {
int ni = i + ki;
int nj = j + kj;
if(ni >= 0 && ni < height && nj >= 0 && nj < width){
if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
sumRed += image[ni][nj].rgbtRed;
sumGreen += image[ni][nj].rgbtGreen;
sumBlue += image[ni][nj].rgbtBlue;
Expand All @@ -139,7 +93,6 @@ void blur(int height, int width, RGBTRIPLE image[height][width]){
temp[i][j].rgbtBlue = (uint8_t)(sumBlue / count);
}
}
// Copy blurred array back to orig
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
image[i][j] = temp[i][j];
Expand All @@ -149,22 +102,37 @@ void blur(int height, int width, RGBTRIPLE image[height][width]){
free(temp);
}

// Blur image

void brightness(int height, int width, RGBTRIPLE image[height][width], int value) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int r = image[i][j].rgbtRed + value;
int g = image[i][j].rgbtGreen + value;
int b = image[i][j].rgbtBlue + value;
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
image[i][j].rgbtRed = r;
image[i][j].rgbtGreen = g;
image[i][j].rgbtBlue = b;
}
}
}

void vignette(int height, int width, RGBTRIPLE image[height][width]){
float cx = width / 2.0; // center of the image
float cy= height / 2.0;
float max_dis= sqrt(cx * cx + cy * cy);
for(int i = 0; i < height; i++){
for(int j = 0; j < width; j++){
void vignette(int height, int width, RGBTRIPLE image[height][width]) {
float cx = width / 2.0;
float cy = height / 2.0;
float max_dis = sqrt(cx * cx + cy * cy);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
float disx = j - cx;
float disy = i - cy;
float dist= sqrt(disx * disx + disy * disy);
// (0.0 = dark, 1.0 = og)
float vig = 1.0 - (dist/ max_dis);
if(vig< 0.0) vig = 0.0;
if(vig > 1.0) vig = 1.0;
float dist = sqrt(disx * disx + disy * disy);
float vig = 1.0 - (dist / max_dis);
if (vig < 0.0) vig = 0.0;
if (vig > 1.0) vig = 1.0;
image[i][j].rgbtRed = (int)(image[i][j].rgbtRed * vig);
image[i][j].rgbtGreen = (int)(image[i][j].rgbtGreen * vig);
image[i][j].rgbtBlue = (int)(image[i][j].rgbtBlue * vig);
Expand Down
5 changes: 3 additions & 2 deletions helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ void reflect(int height, int width, RGBTRIPLE image[height][width]);

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

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