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
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,18 @@ The result is clamped between 0 and 255 and replaces the original pixel value. T

---

### 8.) The Glow Algorithm

The “Glow” filter gives bright regions of an image a soft, luminous halo, similar to a cinematic bloom effect. This filter works by blending the original image with a blurred version of itself.

The algorithm first creates a copy of the image and applies a mild box blur (using a smaller kernel than the main blur filter) to it. Then, for each pixel, the final color values are calculated by combining the original pixel's color with the new blurred pixel's color using a weighted average:

- `finalRed = 0.7 * originalRed + 0.3 * blurredRed`
- `finalGreen = 0.7 * originalGreen + 0.3 * blurredGreen`
- `finalBlue = 0.7 * originalBlue + 0.3 * blurredBlue`

The resulting values are rounded to the nearest integer and capped at 255. This process brightens the image and causes the light to "bleed" from bright areas into darker ones, creating a soft, luminous effect.

### Usage

To apply a filter via command-line:
Expand All @@ -186,6 +198,13 @@ To apply a filter via command-line:
- `b`: blur
- `i`: invert
- `v`: vignette
- `G`: glow
- `t`: threshold
- `d`: edge detection
- `B <value>`: brightness

Example for glow:
./filter -G input.bmp output.bmp

For vignette:
```
Expand Down
8 changes: 5 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 = "bgrsivtdB:";
char *filters = "bgrsivtdGB:";


char filterArr[argc-3];
Expand Down Expand Up @@ -133,7 +133,6 @@ int main(int argc, char *argv[])
case 't':
threshold(height, width, image);
break;

case 'd': // Edge Detection
detect_edges(height, width, image);
break;
Expand All @@ -144,6 +143,9 @@ int main(int argc, char *argv[])
brightness(height, width, image, brightness_value);
break;
}
case 'G':
glow(height, width, image);
break;
default:
printf("Unknown filter: %c\n", filterArr[i]);
free(image);
Expand Down Expand Up @@ -179,4 +181,4 @@ int main(int argc, char *argv[])
fclose(inptr);
fclose(outptr);
return 0;
}
}
Binary file removed filter.exe
Binary file not shown.
74 changes: 73 additions & 1 deletion helpers.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#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;
Expand Down Expand Up @@ -283,4 +284,75 @@ void detect_edges(int height, int width, RGBTRIPLE image[height][width])
for (int i = 0; i < height; i++)
free(copy[i]);
free(copy);
}
}
void glow(int height, int width, RGBTRIPLE image[height][width])
{
// Step 1: make a copy of the original
RGBTRIPLE **original = malloc(height * sizeof(RGBTRIPLE *));
RGBTRIPLE **blurred = malloc(height * sizeof(RGBTRIPLE *));
for (int i = 0; i < height; i++)
{
original[i] = malloc(width * sizeof(RGBTRIPLE));
blurred[i] = malloc(width * sizeof(RGBTRIPLE));
for (int j = 0; j < width; j++)
{
original[i][j] = image[i][j];
}
}

// Step 2: apply a *mild* blur to copy (smaller kernel)
int kernelSize = 11;
int offset = kernelSize / 2;

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, nj = j + kj;
if (ni >= 0 && ni < height && nj >= 0 && nj < width)
{
sumRed += original[ni][nj].rgbtRed;
sumGreen += original[ni][nj].rgbtGreen;
sumBlue += original[ni][nj].rgbtBlue;
count++;
}
}
}

blurred[i][j].rgbtRed = sumRed / count;
blurred[i][j].rgbtGreen = sumGreen / count;
blurred[i][j].rgbtBlue = sumBlue / count;
}
}

// Step 3: blend original + blurred to produce glow
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
float blend = 0.3; // glow intensity
int newRed = (1 - blend) * original[i][j].rgbtRed + blend * blurred[i][j].rgbtRed;
int newGreen = (1 - blend) * original[i][j].rgbtGreen + blend * blurred[i][j].rgbtGreen;
int newBlue = (1 - blend) * original[i][j].rgbtBlue + blend * blurred[i][j].rgbtBlue;

image[i][j].rgbtRed = min(255, newRed);
image[i][j].rgbtGreen = min(255, newGreen);
image[i][j].rgbtBlue = min(255, newBlue);
}
}

// Step 4: cleanup
for (int i = 0; i < height; i++)
{
free(original[i]);
free(blurred[i]);
}
free(original);
free(blurred);
}
3 changes: 2 additions & 1 deletion helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ void brightness(int height, int width, RGBTRIPLE image[height][width], int value
// Vignette filter
void vignette(int height, int width, RGBTRIPLE image[height][width]);


// Glow filter
void glow(int height, int width, RGBTRIPLE image[height][width]);
#endif
Loading